ascii_invoicer 2.5.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/bin/ascii +722 -0
- data/latex/ascii-brief.cls +425 -0
- data/latex/ascii-brief.sty +46 -0
- data/lib/ascii_invoicer.rb +17 -0
- data/lib/ascii_invoicer/InvoiceProject.rb +356 -0
- data/lib/ascii_invoicer/ascii_logger.rb +64 -0
- data/lib/ascii_invoicer/filters.rb +129 -0
- data/lib/ascii_invoicer/generators.rb +209 -0
- data/lib/ascii_invoicer/hash_transformer.rb +23 -0
- data/lib/ascii_invoicer/mixins.rb +268 -0
- data/lib/ascii_invoicer/projectFileReader.rb +106 -0
- data/lib/ascii_invoicer/rfc5322_regex.rb +40 -0
- data/lib/ascii_invoicer/settings_manager.rb +62 -0
- data/lib/ascii_invoicer/texwriter.rb +105 -0
- data/lib/ascii_invoicer/tweaks.rb +25 -0
- data/lib/ascii_invoicer/version.rb +3 -0
- data/repl/ascii +2 -0
- data/settings/default-settings.yml +76 -0
- data/settings/settings_template.yml +54 -0
- data/templates/default.yml.erb +74 -0
- data/templates/document.tex.erb +87 -0
- metadata +297 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 186d774a2d826b6b83265d7597ebb7009a321d4f
|
4
|
+
data.tar.gz: f94639520acbbcee90c511f7539442dd7f7602f6
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 4e3d3887e9432fde377decb43b2a2e44383ee73ea04cbe0b75069cb5623a2f095ab95388f6633a676bba7e057f2c64bc63ca1c92f9dd4b3674bbe5aa6d7f49b3
|
7
|
+
data.tar.gz: 9865ad5aea22a6e4b8e6f42ffa73f571ae0410014da6c3286646409d55e415aeb8f3b8b81dca227fa9dc67287d8627c6e7e13a510a51d316739664b3316a0818
|
data/bin/ascii
ADDED
@@ -0,0 +1,722 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'pp'
|
4
|
+
require 'csv'
|
5
|
+
require 'yaml'
|
6
|
+
require 'thor'
|
7
|
+
require 'euro'
|
8
|
+
require 'paint'
|
9
|
+
require 'luigi'
|
10
|
+
require 'logger'
|
11
|
+
require 'textboxes'
|
12
|
+
require 'hash-graft'
|
13
|
+
|
14
|
+
#finding myself
|
15
|
+
$SCRIPT_PATH = File.split(File.expand_path(__FILE__))[0]
|
16
|
+
$GEM_PATH = File.split($SCRIPT_PATH)[0]
|
17
|
+
|
18
|
+
#require my libraries
|
19
|
+
require "#{$GEM_PATH}/lib/ascii_invoicer"
|
20
|
+
|
21
|
+
# initialize settings
|
22
|
+
settingsmanager = SettingsManager.new({
|
23
|
+
:homedir_path => File.join(Dir.home, ".ascii-invoicer.yml"),
|
24
|
+
:template_path => File.join($GEM_PATH, "/settings/settings_template.yml"),
|
25
|
+
:default_path => File.join($GEM_PATH, "/settings/default-settings.yml")
|
26
|
+
})
|
27
|
+
$SETTINGS = settingsmanager.settings
|
28
|
+
|
29
|
+
#initialize global logger
|
30
|
+
$logger = AsciiLogger.new "Ascii-Invoicer", $SETTINGS.log_file
|
31
|
+
|
32
|
+
## path to the source code
|
33
|
+
$SETTINGS.script_path = $SCRIPT_PATH
|
34
|
+
$SETTINGS.gem_path = $GEM_PATH
|
35
|
+
|
36
|
+
## Version of the software
|
37
|
+
$SETTINGS.version = $VERSION = AsciiInvoicer::VERSION
|
38
|
+
|
39
|
+
## path to the project File, here we expand the "~"
|
40
|
+
$SETTINGS.path = File.expand_path $SETTINGS.path
|
41
|
+
|
42
|
+
|
43
|
+
## "security"
|
44
|
+
#error "settings:editor is an elaborate string: \"#{$SETTINGS.editor}\"!\nDANGEROUS!" if $SETTINGS.editor.include? " "
|
45
|
+
$logger.error "settings:latex is an elaborate string: \"#{$SETTINGS.latex}\"!\nDANGEROUS!" if $SETTINGS.latex.include? " "
|
46
|
+
$logger.error "settings:output_path is an elaborate string: \"#{$SETTINGS.output_path}\"!\nDANGEROUS!" if $SETTINGS.output_path.include? " "
|
47
|
+
|
48
|
+
|
49
|
+
## bootstraping the plumber, first run creates all folders
|
50
|
+
unless File.exists? $SETTINGS.path
|
51
|
+
$logger.fatal "path #{$SETTINGS.path} does not exists"
|
52
|
+
exit
|
53
|
+
end
|
54
|
+
$PLUMBER = Luigi.new $SETTINGS, InvoiceProject
|
55
|
+
$PLUMBER.create_dir :storage unless $PLUMBER.check_dir :storage
|
56
|
+
$PLUMBER.create_dir :working unless $PLUMBER.check_dir :working
|
57
|
+
$PLUMBER.create_dir :archive unless $PLUMBER.check_dir :archive
|
58
|
+
$PLUMBER.create_dir :templates unless $PLUMBER.check_dir :templates
|
59
|
+
$logger.error "template not found!\n#{$PLUMBER.dirs[:templates]}" unless $PLUMBER.check_dir :templates
|
60
|
+
|
61
|
+
$SETTINGS.plumber_dirs = $PLUMBER.dirs
|
62
|
+
|
63
|
+
|
64
|
+
|
65
|
+
## here coms thor
|
66
|
+
class Commander < Thor
|
67
|
+
include Thor::Actions
|
68
|
+
include AsciiInvoicer
|
69
|
+
include AsciiMixins
|
70
|
+
|
71
|
+
|
72
|
+
package_name "ascii invoicer"
|
73
|
+
#argument :first, :type => :numeric
|
74
|
+
map "-l" => :list
|
75
|
+
map "l" => :list
|
76
|
+
map "o" => :offer
|
77
|
+
map "ls" => :list
|
78
|
+
map "dir" => :list
|
79
|
+
map "show" => :display
|
80
|
+
map "-d" => :display
|
81
|
+
map "close" => :archive
|
82
|
+
map "-i" => :invoice
|
83
|
+
map "-o" => :offer
|
84
|
+
map "-V" => :version
|
85
|
+
map "--version" => :version
|
86
|
+
map "config" => :settings
|
87
|
+
map "history" => :log
|
88
|
+
#map "-e" => :edit #depricated
|
89
|
+
|
90
|
+
class_option :verbose, :aliases=> "-v", :type => :boolean, :default => $SETTINGS.verbose, :desc => "Change default in #{$SETTINGS.settings_homedir_path}"
|
91
|
+
#class_option "keep-log", :aliases=> "-k", :type => :boolean
|
92
|
+
|
93
|
+
no_commands{
|
94
|
+
def open_projects(names, options)
|
95
|
+
$SETTINGS.verbose = true if options[:verbose]
|
96
|
+
if options[:file]
|
97
|
+
return [InvoiceProject.new({path => options[:file], settings => $SETTINGS})]
|
98
|
+
|
99
|
+
else
|
100
|
+
if options[:all]
|
101
|
+
available_projects = $PLUMBER.open_projects_all()
|
102
|
+
elsif options[:archive]
|
103
|
+
available_projects = $PLUMBER.open_projects_archive(options[:archive])
|
104
|
+
else
|
105
|
+
available_projects = $PLUMBER.open_projects_working()
|
106
|
+
end
|
107
|
+
|
108
|
+
projects = names.map{|name|
|
109
|
+
if name.class == String and name =~ /^\d*$/
|
110
|
+
available_projects[ (name.to_i - 1) ]
|
111
|
+
else
|
112
|
+
(available_projects.lookup_by_name name) + (available_projects.lookup_by_index name)
|
113
|
+
end
|
114
|
+
}.flatten.uniq
|
115
|
+
if projects.count < 1
|
116
|
+
$logger.error "Nothing found, containing #{names}."
|
117
|
+
#exit
|
118
|
+
end
|
119
|
+
return projects.select{|p|p}
|
120
|
+
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
def render_projects(projects, type, options)
|
125
|
+
projects.each{|project|
|
126
|
+
if project.validate type or options[:force]
|
127
|
+
puts "% RENDERING"
|
128
|
+
project.create_tex(type, options[:stdout]) unless project.nil?
|
129
|
+
else
|
130
|
+
$logger.error "Cannot create an #{type.to_s} from \"#{project.name}\". No valid #{type}: #{project.blockers(type).join ','})"
|
131
|
+
end
|
132
|
+
}
|
133
|
+
end
|
134
|
+
}
|
135
|
+
|
136
|
+
|
137
|
+
desc "new NAME", "Creating a new project"
|
138
|
+
method_option :dont_edit, :type=>:boolean, :aliases => "-d",
|
139
|
+
:lazy_default=> true, :required => false, :desc => "do not edit a new file after creation"
|
140
|
+
method_option :template, :type=>:string, :aliases => "-t",
|
141
|
+
:default => "default", :required => false, :desc => "specify a template"
|
142
|
+
method_option :editor, :type => :string, :aliases => '-e',
|
143
|
+
:default => $SETTINGS.editor, :desc => "specify which editor to use, see #{$SETTINGS.settings_homedir_path}"
|
144
|
+
def new(name)
|
145
|
+
template = options[:template].to_sym
|
146
|
+
unless $PLUMBER.templates.keys.include? template
|
147
|
+
$logger.fatal "There is not such template \"#{template}\" "
|
148
|
+
exit
|
149
|
+
end
|
150
|
+
|
151
|
+
project = $PLUMBER.new_project name, template
|
152
|
+
if project
|
153
|
+
puts project.path
|
154
|
+
puts "creating a new project name #{name}" if project
|
155
|
+
edit_files $PLUMBER.get_project_file_path name unless options[:dont_edit]
|
156
|
+
else
|
157
|
+
puts "was not able to create #{name}"
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
|
162
|
+
desc "edit NAMES", "Edit project"
|
163
|
+
method_option :settings, :type=>:boolean, :aliases => '-s',
|
164
|
+
:lazy_default=> true, :required => false, :desc => "edit settings"
|
165
|
+
method_option :archive,
|
166
|
+
:type=>:numeric, :aliases => "-a", :default => nil,
|
167
|
+
:lazy_default=> Date.today.year, :required => false, :desc => "Open File from archive YEAR"
|
168
|
+
method_option :editor, :type => :string, :aliases => '-e',
|
169
|
+
:default => $SETTINGS.editor, :desc => "specify which editor to use, see #{$SETTINGS.settings_homedir_path}"
|
170
|
+
method_option :template,
|
171
|
+
:type=>:string, :aliases => "-t", :default => nil,
|
172
|
+
:required => false, :desc => "Edit a template file"
|
173
|
+
|
174
|
+
def edit( *names )
|
175
|
+
if options[:settings]
|
176
|
+
paths = [ $SETTINGS.settings_homedir_path ]
|
177
|
+
elsif options[:template]
|
178
|
+
path = $PLUMBER.templates[ options[:template].to_sym ]
|
179
|
+
if not path.nil? and File.exists? path
|
180
|
+
paths = [path]
|
181
|
+
else
|
182
|
+
puts "no such template"
|
183
|
+
exit 1
|
184
|
+
end
|
185
|
+
else
|
186
|
+
projects = open_projects names, options
|
187
|
+
paths= projects.map{ |project| project.path }
|
188
|
+
|
189
|
+
if options[:archive]
|
190
|
+
map = $PLUMBER.map_project_files_archive(options[:archive])
|
191
|
+
else
|
192
|
+
map = $PLUMBER.map_project_files_working()
|
193
|
+
end
|
194
|
+
map.each{|k,v|
|
195
|
+
names.each{|name|
|
196
|
+
if k.downcase.include? name.downcase
|
197
|
+
paths += [v]
|
198
|
+
end
|
199
|
+
}
|
200
|
+
}
|
201
|
+
paths.uniq!
|
202
|
+
|
203
|
+
#pp paths
|
204
|
+
$logger.info "opening #{paths}", :stdo
|
205
|
+
end
|
206
|
+
|
207
|
+
if paths.size > 0
|
208
|
+
edit_files paths, options[:editor]
|
209
|
+
else
|
210
|
+
puts "nothing found (#{names})"
|
211
|
+
end
|
212
|
+
end
|
213
|
+
|
214
|
+
|
215
|
+
|
216
|
+
desc "list", "List current Projects"
|
217
|
+
method_option :archive,
|
218
|
+
:type=>:numeric, :aliases => "-a",
|
219
|
+
:lazy_default=> Date.today.year, :required => false, :desc => "list archived projects"
|
220
|
+
method_option :archives,
|
221
|
+
:type=>:boolean,
|
222
|
+
:lazy_default=> true, :required => false, :desc => "lists all years for which there are archives"
|
223
|
+
method_option :all, :type=>:boolean,
|
224
|
+
:lazy_default=> true, :required => false, :desc => "lists all projects, ever"
|
225
|
+
method_option :templates, :type=>:boolean,
|
226
|
+
:lazy_default=> true, :required => false, :desc => "lists all templates"
|
227
|
+
method_option :paths, :type=>:boolean, :aliases => '-p',
|
228
|
+
:lazy_default=> true, :required => false, :desc => "list paths to .yml files"
|
229
|
+
|
230
|
+
|
231
|
+
method_option :csv, :type=>:boolean,
|
232
|
+
:lazy_default=> true, :required => false, :desc => "output as csv"
|
233
|
+
method_option :sort, :type=>:string,
|
234
|
+
:required => false, :desc => "sort by [date | index | name | manager]",
|
235
|
+
:enum => ['date' , 'index', 'name', 'manager']
|
236
|
+
|
237
|
+
method_option :final, :type=>:boolean,
|
238
|
+
:lazy_default=> true, :required => false, :desc => "list shows final sum"
|
239
|
+
|
240
|
+
method_option :caterers, :type=>:boolean,
|
241
|
+
:lazy_default=> true, :required => false, :desc => "list caterers"
|
242
|
+
|
243
|
+
method_option :blockers, :type=>:boolean, :aliases => '-b',
|
244
|
+
:lazy_default=> true, :required => false, :desc => "list blockers"
|
245
|
+
|
246
|
+
method_option :errors, :type=>:boolean, :aliases => '-e',
|
247
|
+
:lazy_default=> true, :required => false, :desc => "list errors"
|
248
|
+
|
249
|
+
method_option :simple, :type=>:boolean, :aliases => '-s',
|
250
|
+
:lazy_default=> true, :required => false, :desc => "overrides the verbose setting"
|
251
|
+
|
252
|
+
method_option :colors, :type=>:boolean, :aliases => '-c', :default => $SETTINGS.colors,
|
253
|
+
:lazy_default=> true, :required => false, :desc => "overrides the colors setting"
|
254
|
+
|
255
|
+
method_option :filter, :type=>:hash, :aliases => '-f',
|
256
|
+
:required => false, :desc => "filter by manager, caterer etc (experimental)"
|
257
|
+
|
258
|
+
method_option :no_colors, :type=>:boolean, :aliases => '-n',
|
259
|
+
:lazy_default=> true, :required => false, :desc => "overrides the colors setting"
|
260
|
+
|
261
|
+
method_option :details, :type=>:array, :aliases => '-d',
|
262
|
+
:required => false, :desc => "adds details"
|
263
|
+
|
264
|
+
method_option :edit, :type=>:array,
|
265
|
+
:required => false, :desc => "open all listed files for edit"
|
266
|
+
|
267
|
+
def list
|
268
|
+
hash = {}
|
269
|
+
hash[:verbose] = (options[:verbose] and !options[:simple])
|
270
|
+
hash[:colors] = (options[:colors] and !options[:no_colors])
|
271
|
+
hash[:errors] = options[:errors]
|
272
|
+
hash[:blockers] = options[:blockers]
|
273
|
+
hash[:caterers] = options[:caterers]
|
274
|
+
hash[:details] = options[:details]
|
275
|
+
|
276
|
+
if options[:paths]
|
277
|
+
map = $PLUMBER.map_project_files_working()
|
278
|
+
map = $PLUMBER.map_project_files_archive(options[:archive]) if options[:archive]
|
279
|
+
table = Textboxes.new
|
280
|
+
map.each{|name, path| table.add_row [name, path] }
|
281
|
+
puts table
|
282
|
+
exit
|
283
|
+
end
|
284
|
+
|
285
|
+
if not options[:sort].nil? and [:date, :name, :index].include? options[:sort].to_sym
|
286
|
+
sort = options[:sort].to_sym
|
287
|
+
elsif $SETTINGS.list_sort?
|
288
|
+
sort = $SETTINGS.list_sort.to_sym
|
289
|
+
else
|
290
|
+
sort = :date
|
291
|
+
end
|
292
|
+
|
293
|
+
if options[:all]
|
294
|
+
projects = $PLUMBER.open_projects_all() #TODO
|
295
|
+
elsif options[:archives]
|
296
|
+
puts $PLUMBER.map_archive_years.keys
|
297
|
+
return
|
298
|
+
elsif options[:templates]
|
299
|
+
puts $PLUMBER.templates.keys
|
300
|
+
return
|
301
|
+
elsif options[:archive]
|
302
|
+
projects = $PLUMBER.open_projects_archive(options[:archive], sort)
|
303
|
+
else
|
304
|
+
projects = $PLUMBER.open_projects_working(sort)
|
305
|
+
end
|
306
|
+
|
307
|
+
if options[:filter]
|
308
|
+
projects = $PLUMBER.filter_by projects, options[:filter]
|
309
|
+
end
|
310
|
+
|
311
|
+
if options[:csv]
|
312
|
+
projects = $PLUMBER.sort_projects(projects, :index)
|
313
|
+
print_project_list_csv projects
|
314
|
+
elsif options[:yaml]
|
315
|
+
print_project_list_yaml projects
|
316
|
+
else
|
317
|
+
print_project_list(projects, hash)
|
318
|
+
end
|
319
|
+
|
320
|
+
if options[:edit]
|
321
|
+
all_paths= projects.map { |project| project.path }
|
322
|
+
|
323
|
+
paths = options[:edit].map{|index| all_paths[index.to_i-1] }
|
324
|
+
puts paths
|
325
|
+
|
326
|
+
if paths.size > 0
|
327
|
+
edit_files paths, options[:editor]
|
328
|
+
else
|
329
|
+
puts "nothing found (#{names})"
|
330
|
+
end
|
331
|
+
end
|
332
|
+
end
|
333
|
+
|
334
|
+
desc "templates", "List or add templates"
|
335
|
+
method_option :add, :type=>:boolean,
|
336
|
+
:lazy_default=> true, :required => false, :desc => "Adds template changes to index just like ascii add does to projects."
|
337
|
+
|
338
|
+
def templates
|
339
|
+
if options[:add]
|
340
|
+
path = $PLUMBER.dirs[:templates]
|
341
|
+
$PLUMBER.git_update_path(path) if $PLUMBER.open_git()
|
342
|
+
else
|
343
|
+
puts $PLUMBER.templates.keys
|
344
|
+
end
|
345
|
+
end
|
346
|
+
|
347
|
+
desc "csv", "Equal to: ascii list --all --csv --sort=index --filter event/date:#{Date.today.year}"
|
348
|
+
method_option :year,
|
349
|
+
:type=>:numeric, :aliases => "-y",
|
350
|
+
:default=> Date.today.year, :required => false, :desc => "Year to export"
|
351
|
+
def csv
|
352
|
+
invoke :list, [], csv:true, all:true, sort:"index", filter:{"event/date"=>options[:year].to_s}# where is this documented
|
353
|
+
end
|
354
|
+
|
355
|
+
desc "search QUERY", "Search everything, only one query currently"
|
356
|
+
def search *queries
|
357
|
+
queries.map!{|query|
|
358
|
+
path, term = query.split ?:
|
359
|
+
{path => term}
|
360
|
+
}
|
361
|
+
puts "#{queries[0].keys[0]}: #{queries[0].values[0]}"
|
362
|
+
invoke :list, [], all:true, filter:queries[0]#, details:queries[0].keys
|
363
|
+
end
|
364
|
+
|
365
|
+
desc "whoami", "Invoke settings --show manager_name"
|
366
|
+
def whoami
|
367
|
+
invoke :settings, [], show:"manager_name"
|
368
|
+
end
|
369
|
+
|
370
|
+
desc "calendar", "Create a calendar file from all caterings named \"invoicer.ics\""
|
371
|
+
def calendar
|
372
|
+
projects = $PLUMBER.open_projects_all()
|
373
|
+
valid = true
|
374
|
+
projects.each{|project|
|
375
|
+
unless project.validate(:calendar)
|
376
|
+
valid = false
|
377
|
+
$logger.error "error in event/date in \"#{project.name}\""
|
378
|
+
end
|
379
|
+
|
380
|
+
}
|
381
|
+
unless valid
|
382
|
+
$logger.error "Can't create Calendar."
|
383
|
+
exit
|
384
|
+
end
|
385
|
+
create_cal_file $PLUMBER.open_projects_all()
|
386
|
+
end
|
387
|
+
|
388
|
+
|
389
|
+
|
390
|
+
desc "archive NAME", "Move project to archive"
|
391
|
+
method_option :force,:type=>:boolean,
|
392
|
+
:lazy_default=> true, :required => false,
|
393
|
+
:desc => "Force archiving projects that are invalid."
|
394
|
+
def archive( *names )
|
395
|
+
projects = open_projects names, options
|
396
|
+
project = projects[0]
|
397
|
+
return false unless project
|
398
|
+
|
399
|
+
year = project.date.year
|
400
|
+
prefix = project.data[:invoice][:number]
|
401
|
+
prefix ||= ""
|
402
|
+
prefix += "canceled" if project.data[:canceled]
|
403
|
+
|
404
|
+
puts options
|
405
|
+
|
406
|
+
unless project.validate(:archive) or options[:force] or project.data[:canceled]
|
407
|
+
$logger.error "\"#{project.name}\" contains errors\n(#{project.errors.join(',')})"
|
408
|
+
else
|
409
|
+
new_path = $PLUMBER.archive_project project, Date.today.year, prefix
|
410
|
+
puts new_path
|
411
|
+
end
|
412
|
+
end
|
413
|
+
|
414
|
+
desc "reopen YEAR NAME", "reopen an archived project"
|
415
|
+
def reopen(year, name)
|
416
|
+
projects = $PLUMBER.open_projects_archive year
|
417
|
+
project = projects.lookup_by_name name
|
418
|
+
if project.count > 1
|
419
|
+
$logger.error "Ambigous results"
|
420
|
+
puts project
|
421
|
+
exit
|
422
|
+
else
|
423
|
+
project = project[0]
|
424
|
+
puts project.path
|
425
|
+
end
|
426
|
+
|
427
|
+
#unless $PLUMBER.unarchive_project project, year
|
428
|
+
# $logger.error "Can't unarchive #{name}, checks names of current projects for duplicates!"
|
429
|
+
#end
|
430
|
+
end
|
431
|
+
|
432
|
+
|
433
|
+
|
434
|
+
|
435
|
+
|
436
|
+
|
437
|
+
desc "display NAMES", "Shows information about a project in different ways"
|
438
|
+
method_option :archive,
|
439
|
+
:type=>:numeric, :aliases => "-a",
|
440
|
+
:default => nil,
|
441
|
+
:lazy_default=> Date.today.year,
|
442
|
+
:required => false,
|
443
|
+
:desc => "Select File from archive YEAR"
|
444
|
+
method_option :all, :type=>:boolean,
|
445
|
+
:default=> false, :lazy_default=> true, :required => false,
|
446
|
+
:desc => "Select File from any archive and current working directory "
|
447
|
+
method_option :name, :type=>:boolean,
|
448
|
+
:default=> false, :lazy_default=> true, :required => false,
|
449
|
+
:desc => "Display only the name"
|
450
|
+
method_option :offer, :type=>:boolean,
|
451
|
+
:default=> false, :lazy_default=> true, :required => false,
|
452
|
+
:desc => "Display the offer"
|
453
|
+
method_option :invoice, :type=>:boolean,
|
454
|
+
:default=> false, :lazy_default=> true, :required => false,
|
455
|
+
:desc => "Display the invoice"
|
456
|
+
method_option :csv, :type=>:boolean, :aliases => '-c',
|
457
|
+
:lazy_default=> true, :required => false, :desc => "show as csv"
|
458
|
+
method_option :errors, :type=>:boolean, :aliases => '-e',
|
459
|
+
:lazy_default=> true, :required => false, :desc => "show errors in footer"
|
460
|
+
method_option :products, :type=>:boolean,
|
461
|
+
:default=> false, :lazy_default=> true, :required => false,
|
462
|
+
:desc => "Display only the products for the --offer or --invoice"
|
463
|
+
method_option :caterers, :type=>:boolean,
|
464
|
+
:default=> false, :lazy_default=> true, :required => false,
|
465
|
+
:desc => "Display Caterers"
|
466
|
+
method_option :raw,:type=>:boolean,
|
467
|
+
:default=> false, :lazy_default=> true, :required => false,
|
468
|
+
:desc => ""
|
469
|
+
method_option :costs,:type=>:boolean,
|
470
|
+
:default=> false, :lazy_default=> true, :required => false,
|
471
|
+
:desc => ""
|
472
|
+
method_option :detail, :type=>:string, :banner => "key", :aliases =>"-d",
|
473
|
+
:default => nil, :lazy_default=> "", :required => false,
|
474
|
+
:desc => "output key or all with pp"
|
475
|
+
method_option :pp, :type=>:string, :banner => "key",
|
476
|
+
:default => nil, :lazy_default=> "", :required => false,
|
477
|
+
:desc => "output key or all with pp"
|
478
|
+
# method_option :yaml, :type=>:string, :banner => "key",
|
479
|
+
# :default => nil, :lazy_default=> "", :required => false,
|
480
|
+
# :desc => "output key or all as yaml"
|
481
|
+
method_option :cal, :type=>:boolean,
|
482
|
+
:default => nil, :lazy_default=> "", :required => false,
|
483
|
+
:desc => "output key or all as ical event[s]"
|
484
|
+
def display(*names)
|
485
|
+
projects = open_projects names, options
|
486
|
+
|
487
|
+
projects.each{ |project|
|
488
|
+
$logger.error("No project found!") if project.nil?
|
489
|
+
unless options[:cal] or options[:yaml] or options[:costs] or options[:caterers] or options[:invoice] or options[:offer] or options[:products]
|
490
|
+
fallback= true
|
491
|
+
end
|
492
|
+
|
493
|
+
if not options[:yaml].nil?
|
494
|
+
if options[:yaml] == ''
|
495
|
+
puts project.data.to_yaml
|
496
|
+
else
|
497
|
+
puts project.data.get_path(options[:yaml]).to_yaml
|
498
|
+
end
|
499
|
+
elsif options[:name]
|
500
|
+
puts project.name
|
501
|
+
elsif options[:csv]
|
502
|
+
display_products_csv project
|
503
|
+
elsif options[:raw]
|
504
|
+
raw = project.raw_data
|
505
|
+
raw.delete "cataloge"
|
506
|
+
puts raw.to_yaml
|
507
|
+
elsif not options[:detail].nil?
|
508
|
+
if options[:detail] == ''
|
509
|
+
puts project.data
|
510
|
+
else
|
511
|
+
puts project.data.get_path(options[:detail])
|
512
|
+
end
|
513
|
+
elsif not options[:pp].nil?
|
514
|
+
if options[:pp] == ''
|
515
|
+
pp project.data
|
516
|
+
else
|
517
|
+
pp project.data.get_path(options[:pp])
|
518
|
+
end
|
519
|
+
else
|
520
|
+
if options[:products]
|
521
|
+
puts display_products(project, :offer )
|
522
|
+
puts display_products(project, :invoice) if options[:invoice]
|
523
|
+
else
|
524
|
+
puts display_all(project, :offer , options[:errors]) if options[:offer ]
|
525
|
+
puts display_all(project, :invoice, options[:errors]) if options[:invoice] or fallback
|
526
|
+
end
|
527
|
+
if options[:cal]
|
528
|
+
project.data[:event][:calendaritems].each{|cal|
|
529
|
+
puts cal.to_ical
|
530
|
+
}
|
531
|
+
end
|
532
|
+
if options[:caterers]
|
533
|
+
print "#{project.name}:".ljust(35) if names.length > 1
|
534
|
+
if project.data[:hours][:caterers]
|
535
|
+
puts project.data[:hours][:caterers].map{|name, hours| "#{name} (#{hours})"}.join(", ")
|
536
|
+
else
|
537
|
+
puts "Caterers is empty"
|
538
|
+
end
|
539
|
+
end
|
540
|
+
end
|
541
|
+
}
|
542
|
+
end
|
543
|
+
|
544
|
+
desc "offer NAMES", "Create an offer from project"
|
545
|
+
method_option :archive,
|
546
|
+
:type=>:numeric, :aliases => "-a",
|
547
|
+
:default => nil,
|
548
|
+
:lazy_default=> Date.today.year,
|
549
|
+
:required => false,
|
550
|
+
:desc => "Open File from archive YEAR"
|
551
|
+
method_option :stdout,
|
552
|
+
:type=>:numeric, :aliases => "-s",
|
553
|
+
:lazy_default=> true,
|
554
|
+
:required => false,
|
555
|
+
:desc => "print tex to stdout"
|
556
|
+
method_option :force,:type=>:boolean,
|
557
|
+
:lazy_default=> true, :required => false,
|
558
|
+
:desc => "Ignore validator."
|
559
|
+
def offer(*names)
|
560
|
+
projects = open_projects names, options
|
561
|
+
render_projects projects, :offer, options
|
562
|
+
end
|
563
|
+
|
564
|
+
desc "invoice NAMES", "Create an invoice from project"
|
565
|
+
method_option :archive,
|
566
|
+
:type=>:numeric, :aliases => "-a",
|
567
|
+
:default => nil,
|
568
|
+
:lazy_default=> Date.today.year,
|
569
|
+
:required => false,
|
570
|
+
:desc => "Open File from archive YEAR"
|
571
|
+
method_option :stdout,
|
572
|
+
:type=>:numeric, :aliases => "-s",
|
573
|
+
:lazy_default=> true,
|
574
|
+
:required => false,
|
575
|
+
:desc => "print tex to stdout"
|
576
|
+
method_option :force,:type=>:boolean,
|
577
|
+
:lazy_default=> true, :required => false,
|
578
|
+
:desc => "Ignore validator."
|
579
|
+
def invoice( *names)
|
580
|
+
projects = open_projects names, options
|
581
|
+
render_projects projects, :invoice, options
|
582
|
+
end
|
583
|
+
|
584
|
+
|
585
|
+
|
586
|
+
|
587
|
+
|
588
|
+
|
589
|
+
desc "status", "Git Integration"
|
590
|
+
def status
|
591
|
+
$PLUMBER.git_status() if $PLUMBER.open_git()
|
592
|
+
end
|
593
|
+
|
594
|
+
|
595
|
+
desc "add NAMES", "Git Integration"
|
596
|
+
method_option :template,
|
597
|
+
:type=>:string, :aliases => "-t", :default => nil,
|
598
|
+
:required => false, :desc => "Adds a template file"
|
599
|
+
method_option :archive,
|
600
|
+
:type=>:numeric, :aliases => "-a",
|
601
|
+
:default => nil,
|
602
|
+
:lazy_default=> Date.today.year,
|
603
|
+
:required => false,
|
604
|
+
:desc => "Add File from archive YEAR"
|
605
|
+
|
606
|
+
def add *names
|
607
|
+
if options[:template]
|
608
|
+
path = $PLUMBER.templates[ options[:template].to_sym ]
|
609
|
+
if not path.nil? and File.exists? path
|
610
|
+
$PLUMBER.git_update_path(path) if $PLUMBER.open_git()
|
611
|
+
end
|
612
|
+
end
|
613
|
+
|
614
|
+
projects = open_projects names, options
|
615
|
+
projects.each {|project|
|
616
|
+
path = project.project_folder
|
617
|
+
if not path.nil? and File.exists? path
|
618
|
+
$PLUMBER.git_update_path(path) if $PLUMBER.open_git()
|
619
|
+
end
|
620
|
+
}
|
621
|
+
status()
|
622
|
+
end
|
623
|
+
|
624
|
+
desc "commit", "Git Integration"
|
625
|
+
method_option :message,
|
626
|
+
:type=>:string, :aliases => "-m", :default => nil,
|
627
|
+
:lazy_default=> Date.today.year, :required => true,
|
628
|
+
:desc => "Open File from archive YEAR"
|
629
|
+
def commit
|
630
|
+
$PLUMBER.git_commit(options[:message]) if $PLUMBER.open_git()
|
631
|
+
end
|
632
|
+
|
633
|
+
desc "push", "Git Integration"
|
634
|
+
def push
|
635
|
+
$PLUMBER.git_push() if $PLUMBER.open_git()
|
636
|
+
end
|
637
|
+
|
638
|
+
desc "pull", "Git Integration"
|
639
|
+
def pull
|
640
|
+
$PLUMBER.git_pull() if $PLUMBER.open_git()
|
641
|
+
end
|
642
|
+
|
643
|
+
desc "log", "Git Integration"
|
644
|
+
method_option :count,
|
645
|
+
:type=>:numeric, :aliases => "-c",
|
646
|
+
:default => 30,
|
647
|
+
:lazy_default=> 1000,
|
648
|
+
:required => false,
|
649
|
+
:desc => "Max count of history entries"
|
650
|
+
def log
|
651
|
+
$PLUMBER.git_log(options[:count]) if $PLUMBER.open_git()
|
652
|
+
end
|
653
|
+
|
654
|
+
|
655
|
+
|
656
|
+
|
657
|
+
|
658
|
+
desc "settings", "View settings"
|
659
|
+
method_option :edit,
|
660
|
+
:type=>:boolean, :aliases => "-e",
|
661
|
+
:lazy_default=> false,
|
662
|
+
:required => false,
|
663
|
+
:desc => "edit your settings"
|
664
|
+
method_option :show,
|
665
|
+
:type=>:string, :aliases => "-s",
|
666
|
+
:required => false,
|
667
|
+
:desc => "show a specific settings value"
|
668
|
+
|
669
|
+
def settings
|
670
|
+
|
671
|
+
if options[:edit]
|
672
|
+
edit_files $SETTINGS.settings_homedir_path
|
673
|
+
elsif options[:show]
|
674
|
+
value = $SETTINGS.get_path options[:show]
|
675
|
+
if value.class == Hash or value.class == Array
|
676
|
+
puts value.to_yaml
|
677
|
+
elsif value.class == Hashr
|
678
|
+
puts value.to_hash.to_yaml
|
679
|
+
else
|
680
|
+
puts value
|
681
|
+
end
|
682
|
+
else
|
683
|
+
puts $SETTINGS.to_hash.to_yaml
|
684
|
+
end
|
685
|
+
#pp $SETTINGS
|
686
|
+
end
|
687
|
+
|
688
|
+
desc "path", "Return projects storage path"
|
689
|
+
method_option :templates, :type=>:boolean, :aliases => '-t',
|
690
|
+
:lazy_default=> true, :required => false, :desc => "returns templates path"
|
691
|
+
method_option :output, :type=>:boolean, :aliases => '-o',
|
692
|
+
:lazy_default=> true, :required => false, :desc => "returns output path"
|
693
|
+
method_option :script, :type=>:boolean,
|
694
|
+
:lazy_default=> true, :required => false, :desc => "returns script path"
|
695
|
+
def path
|
696
|
+
if options[:script]
|
697
|
+
puts File.split($GEM_PATH)[0]
|
698
|
+
elsif options[:output]
|
699
|
+
puts File.expand_path File.join $SETTINGS.output_path
|
700
|
+
elsif options[:templates]
|
701
|
+
puts $PLUMBER.dirs[:templates]
|
702
|
+
else
|
703
|
+
puts File.join $SETTINGS.path, $SETTINGS.dirs.storage
|
704
|
+
end
|
705
|
+
end
|
706
|
+
|
707
|
+
desc "output", "Equal to: ascii path --output"
|
708
|
+
def output
|
709
|
+
invoke :path, [], output:true
|
710
|
+
end
|
711
|
+
|
712
|
+
desc "version", "Display version"
|
713
|
+
method_option :changed_files, :type=>:boolean, :aliases => '-c',
|
714
|
+
:lazy_default=> true, :required => false, :desc => "show changed files"
|
715
|
+
method_option :fetch, :type=>:boolean, :aliases => '-f',
|
716
|
+
:lazy_default=> true, :required => false, :desc => "update new code (FETCH ONLY != pull)"
|
717
|
+
def version
|
718
|
+
puts "ascii-invoicer v#{$VERSION}"
|
719
|
+
end
|
720
|
+
end
|
721
|
+
|
722
|
+
Commander.start
|