-
Notifications
You must be signed in to change notification settings - Fork 4
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Mysql support and other fixes #11
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
# constants | ||
DATE_FMT = "%Y-%m-%d".freeze # ISO | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you move those constants under There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm fine if you will move it to |
||
INVOICE_LIST_FMT = "%-16s %-32s %-32s %-12s %-12s %-10s".freeze | ||
INVOICE_LIST_HDR = ('-' * 119).freeze | ||
TIMESTAMP_MSQL_FMT = "%Y%m%d %H%M%S %z".freeze # GnuCash-3.x | ||
TIMESTAMP_SQLT_FMT = "%Y-%m-%d %H:%M:%S".freeze |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,19 +1,39 @@ | ||
# stdlib | ||
require "optparse" | ||
require "config" | ||
|
||
module GnuCash | ||
class Invoice | ||
module Runner | ||
class << self | ||
|
||
USAGE = "Usage:\n\n gnucash-invoice [OPTIONS] [invoice-ID]\n\nOptions:\n\n" | ||
EXAMPLE = "\nExamples: | ||
|
||
$ gnucash-invoice -d path-to-sqlitedb inv-1234 | ||
$ gnucash-invoice -a mysql -h db.somewhere.net -d dbname -u user -p sekreet | ||
" | ||
|
||
def run(argv) | ||
|
||
options = parse argv | ||
|
||
unless options[:db] | ||
puts "ERROR: No database selected" | ||
exit 1 | ||
case options[:adapter] | ||
when 'sqlite' | ||
GnuCash.connect! options[:db] | ||
when 'mysql' | ||
GnuCash.connect_mysql!( | ||
options[:host], options[:user], | ||
options[:password], options[:db] | ||
) | ||
else | ||
abort("ERROR: #{options[:adapter]}: unsupported DB adapter") | ||
end | ||
|
||
GnuCash.connect! options[:db] | ||
# Useless? | ||
# unless options[:db] | ||
# abort("ERROR: No database selected for #{options[:adapter]}") | ||
# end | ||
|
||
if options[:invoice_id] | ||
# Print out invoice | ||
|
@@ -22,38 +42,95 @@ def run(argv) | |
end | ||
|
||
# Show known invoices | ||
puts INVOICE_LIST_HDR | ||
puts INVOICE_LIST_FMT % [ | ||
'Invoice ID', 'Customer', 'Reference', 'Opened at', 'Posted at', | ||
'Due at' | ||
] | ||
puts INVOICE_LIST_HDR | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think these two should be constants. I think we should add teminal-table gem instead and use it here: puts Terminal::Table.new({
:headings => ['Invoice ID', 'Customer', 'Reference', 'Opened at', 'Posted at', 'Due at']
:rows => Invoice.all.map { |invoice| [invoice.id, ...] }
}) |
||
Invoice.all.each { |invoice| puts invoice } | ||
|
||
exit 0 | ||
rescue Sequel::DatabaseConnectionError | ||
puts "ERROR: Can't connect to database: #{options[:db].inspect}" | ||
exit 2 | ||
rescue => e | ||
puts "ERROR: #{e}" | ||
exit 3 | ||
|
||
rescue OptionParser::ParseError, OptionParser::MissingArgument => e | ||
abort("ERROR: #{e.message}\n#{USAGE} (see #{$0} -H)") | ||
|
||
rescue GnuCash::NoDatabaseFound, | ||
GnuCash::NoDatabaseConnection, | ||
Sequel::DatabaseConnectionError => e | ||
abort("ERROR: #{options[:db].inspect}: Can't connect to database: #{e}") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's better to use wording: abort("ERROR: Can't connect to database #{options[:db].inspect}\n#{e}") |
||
|
||
# other exceptions beyond this point are *bugs* | ||
# rescue => e | ||
# abort("ERROR: #{options[:db].inspect}: #{e}") | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Just remove this then :D |
||
end | ||
|
||
private | ||
|
||
def parse(argv) | ||
options = { :template => "templates" } | ||
options = { | ||
:adapter => "sqlite", | ||
:host => "localhost", | ||
:template => "templates", | ||
:user => "root" | ||
} | ||
|
||
OptionParser.new do |opts| | ||
opts.on("--dbpath [DATABASE]", | ||
"SQLite database path") do |path| | ||
puts "WARNING: --dbpath is deprecated use --db-path instead" | ||
options[:db] = path | ||
|
||
opts.banner = USAGE | ||
|
||
|
||
# validation by regex looks broken :-( | ||
# <https://bugs.ruby-lang.org/issues/14728> | ||
# <https://bugs.ruby-lang.org/issues/10021> | ||
opts.on( | ||
'-a', '--adapter', '=ADAPTER', %w[sqlite mysql], | ||
'DB adapter, one in [mysql,sqlite]. Default "sqlite"' | ||
) do |adapter| | ||
options[:adapter] = adapter | ||
end | ||
|
||
opts.on("-d", "--db-path [DATABASE]", | ||
"SQLite database path") do |path| | ||
opts.on( | ||
'-d', '--db-path', '=DATABASE', | ||
'DB path (SQLite) OR name (MySQL)', | ||
) do |path| | ||
options[:db] = path | ||
end | ||
|
||
opts.on("-t", "--template [TEMPLATE]", | ||
"Template directory path") do |path| | ||
opts.on( | ||
'-t', '--template', '=TEMPLATE', | ||
'Template directory path' | ||
) do |path| | ||
options[:template] = path | ||
end | ||
|
||
opts.on( | ||
'-h', '--host', '=HOST[:PORT]', | ||
'MySQL host. Default: "localhost" (PORT ignored with this)' | ||
) do |host| | ||
# TO-DO: canonicalize URI? | ||
options[:host] = host | ||
end | ||
|
||
opts.on( | ||
'-u', '--user', '=USER', 'MySQL DB user. Default: "root"' | ||
) do |user| | ||
options[:user] = user | ||
end | ||
|
||
opts.on( | ||
'-p', '--password', '=PASSWORD', 'MySQL DB password' | ||
) do |password| | ||
options[:password] = password | ||
end | ||
|
||
opts.on('-H', '--help', 'Prints this help') do | ||
puts opts | ||
puts EXAMPLE | ||
exit | ||
end | ||
|
||
opts.parse! argv | ||
end | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,19 +1,21 @@ | ||
require "config" | ||
|
||
module GnuCash | ||
module Timestamps | ||
FORMAT = "%Y%m%d%H%M%S" | ||
|
||
def from_timestamp(value) | ||
case value | ||
when ::DateTime then value | ||
when ::DateTime, ::Time then value # GnuCash-3.x | ||
when ::Numeric, /\A\d+\z/ then parse value.to_s | ||
when ::String, /\A\d+\z/ then parse value | ||
else fail "#{value}: don't know how to treat this timestamp" | ||
end | ||
end | ||
|
||
private | ||
|
||
def parse(str) | ||
::DateTime.strptime(str, FORMAT).to_time | ||
::DateTime.strptime(str, TIMESTAMP_SQLT_FMT).to_time | ||
end | ||
end | ||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Probably it's better to change to simply accept
--db
argument that will be a URL like:There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not saying I insist. Just a thought,