lib/wlog/ui/invoice_ui.rb
require 'readline'
require 'tempfile'
require 'wlog/domain/invoice'
require 'wlog/domain/sys_config'
require 'wlog/domain/static_configurations'
require 'wlog/domain/template_helper'
require 'wlog/commands/write_template'
require 'wlog/commands/fetch_git_commits'
require 'wlog/commands/fetch_git_commits_standard'
require 'wlog/tech/git_commit_printer'
require 'erb'
module Wlog
# An interface for the invoices
# @author Simon Symeonidis
class InvoiceUi
include StaticConfigurations
include GitCommitPrinter
def initialize
@strmaker = SysConfig.string_decorator
end
def run
cmd = "default"
while cmd != 'end'
cmd = Readline.readline("[#{@strmaker.red('invoices')}] ") || ""
case cmd
when /^new/ then make_invoice
when /^(ls|show)/ then ls
when /^delete/ then delete(cmd.split.drop 1)
when /^generate/ then generate(cmd.split.drop 1)
when /^commits/ then commits(cmd.split.drop 1)
when 'help' then print_help
when /^end/ then next
else
puts "type 'help' for a list of options"
end
end
end
private
# TODO maybe separate this in the future for better testing.
def generate(rest)
num = rest.first || 1
@invoice = Invoice.find(num.to_i)
if KeyValue.get('git')
# Only attempt to fetch commits if user has set git repo
cmd = FetchGitCommitsStandard.new(@invoice.from, @invoice.to)
cmd.execute
@commits = cmd.commits
end
@log_entries = @invoice.log_entries_within_dates
@issues = [Issue.find(*(@log_entries.collect(&:issue_id).uniq))].compact.flatten
renderer = ERB.new(TemplateHelper.template_s)
output = renderer.result(binding)
WriteTemplate.new(output, @invoice).execute
rescue ActiveRecord::RecordNotFound
puts 'No such invoice'
rescue => e
puts e
end
def delete(rest)
id = rest[0]
cmd = Readline.readline("Are you sure you want to delete invoice ##{id}? [y/n]: ")
return if cmd != 'y'
Invoice.delete(id)
end
def ls
Invoice.all.each do |invoice|
print " [#{invoice.id}] "
print @strmaker.yellow(invoice.from.strftime("%d-%m-%Y"))
print @strmaker.blue(" -> ")
print @strmaker.yellow(invoice.to.strftime("%d-%m-%Y"))
puts " #{invoice.description.lines.first.gsub(/(\r|\n)/, "")[0..49]}..."
end
end
def print_help
['new', 'make a new invoice',
'ls,show', 'list the current invoice templates',
'delete', 'delete an invoice (eg: delete 2)',
'generate', 'generate an invoice using set template (eg: generate 2)',
'commits', 'list out the commits valid for the duration of the invoice'
].each_with_index do |cmd,ix|
print ' ' if ix % 2 == 1
puts cmd
end
end
# TODO this should be extracted for testing
def make_invoice
from_s = Readline.readline("#{@strmaker.blue('From')} (dd-mm-yyyy) ")
to_s = Readline.readline("#{@strmaker.blue('To')} (dd-mm-yyyy) ")
from_d = DateTime.parse(from_s)
to_d = DateTime.parse(to_s + " 23:59")
description = longtext()
Invoice.create(:from => from_d, :to => to_d, :description => description)
end
# TODO: this would have to be factored out at some point. Also I think the
# implementation is crappy. I have to recheck at some point.
def longtext
if ENV['EDITOR'].nil?
count = 0
status = nil
str = ""
until status == :end_text do
line = Readline.readline(@strmaker.blue('> ')).strip
count += 1 if line == ""
count = 0 if line != ""
str.concat(line).concat($/)
status = :end_text and next if count == 2
end
else
t = Tempfile.new('description')
system(ENV['EDITOR'] + ' ' + t.path)
str = File.open(t.path).read
t.unlink
end
str
end
def commits(invoice_id)
inv = Invoice.find_by_id(invoice_id)
repo = KeyValue.get('git')
author = KeyValue.get('author')
unless repo
puts @strmaker.red("You need to set a git repo first")
return
end
command = FetchGitCommits.new(inv.from, inv.to, repo, author)
command.execute
puts
print ' '
puts "git commits for #{@strmaker.yellow(author)}"
puts
print_git_commits(command.commits)
rescue ActiveRecord::RecordNotFound
puts @strmaker.red("No such invoice")
end
end
end