lucadeal 0.2.16 → 0.2.23

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5f17d75af6f101c60eced0ecfb770e39ac66b0f35725a6976f135216a0c75099
4
- data.tar.gz: d3e60d51908e78ab72e177f29affc26864744afb584d1c5dadd507b18ff888f6
3
+ metadata.gz: 5f3d23a1f082ee44833db42f3cf4dbdecc0d078ea3ca6499d5cf77e6d235580a
4
+ data.tar.gz: c2ea468ea064bb865d0b481d9717a03f11afe212f0bfd3b58ac43722116a95e7
5
5
  SHA512:
6
- metadata.gz: bd534c31a33405478cdeba88777481f5c17af6337cf743e2d16a8e5027209a65d1efb8329cf7f6e72318dfea8c3daa1965d9cf1e833ce93b85d24925c17638f6
7
- data.tar.gz: f1d809de08ce94cf7da913c5bc733515f95bba596dc155596880cb4776837113c36f93ee4247c35fe34990f2a45fd758df1bddec3d2e587d182062cdb5893c60
6
+ metadata.gz: 545d6acb5b7837497c30d17a42c6a32611186f2e12f9821d116c9aa3ed9735dc1c8bc2c072d1439c9e21e1fd38d7398de770ffd9fd835352f4565f96a18a19ca
7
+ data.tar.gz: c8cf01067781332a241138ab9b253d282902a3838a19d2f9623d9eb29c6c4a3432e7d0e6818bc67a3e3b3e682e5ba3c4c5c128a90f93b3f91dcadca0285ea2f4
@@ -1,3 +1,35 @@
1
+ ## LucaDeal 0.2.23
2
+
3
+ * implement `luca-deal invoices list --mail`: payment list via HTML mail
4
+
5
+ ## LucaDeal 0.2.22
6
+
7
+ * Breaking change: export key 'value' -> 'amount'
8
+
9
+ ## LucaDeal 0.2.21
10
+
11
+ * Implement `luca-deal fee` subcommands.
12
+ * single invoice creation with contract id fragment.
13
+
14
+ ## LucaDeal 0.2.20
15
+
16
+ * CLI provides `--nu` option. Add JSON output.
17
+ * `luca-deal invoices list --html`, rendering HTML to stdout.
18
+
19
+ ## LucaDeal 0.2.19
20
+
21
+ * CLI id completion on Customer delete, Contract create/delete
22
+ * add `describe` to Customer / Contract
23
+
24
+ ## LucaDeal 0.2.18
25
+
26
+ * Breaking change: restructure CLI in sub-sub command format.
27
+ * Add 'x-customer', 'x-editor' on export to LucaBook
28
+
29
+ ## LucaDeal 0.2.17
30
+
31
+ * `luca-deal export` export JSON for LucaBook
32
+
1
33
  ## LucaDeal 0.2.14
2
34
 
3
35
  * Introduce Product for selling items template.
data/README.md CHANGED
@@ -22,7 +22,67 @@ Or install it yourself as:
22
22
 
23
23
  ## Usage
24
24
 
25
- TODO: Write usage instructions here
25
+ You can create project skelton with `new` sub command.
26
+
27
+ ```
28
+ $ luca-deal new Dir
29
+ ```
30
+
31
+ Example assumes setup with bundler shim. `bundle exec` prefix may be needed in most cases.
32
+
33
+
34
+ ### Manage Contract
35
+
36
+ Customer object can be created by `customer create` subcommand with name.
37
+
38
+ ```
39
+ $ luca-deal customer create CustomerName
40
+ Successfully generated Customer 5976652cc2d9c0ebf4a8646f7a28aa8d6bd2d606
41
+ Edit customer detail.
42
+ ```
43
+
44
+ Customer is filed under `data/customers` as YAML. Detail need to be editted.
45
+ Then, Contract object is created by `contract create` sub command with customer id.
46
+
47
+ ```
48
+ $ luca-deal contract create 5976652cc2d9c0ebf4a8646f7a28aa8d6bd2d606
49
+ uccessfully generated Contract 814c6fc9fffe5566fe8e7ef683b439b355d612dc
50
+ Conditions are tentative. Edit contract detail.
51
+ ```
52
+
53
+ Contract is filed under `data/contracts` as YAML. Detail need to be editted.
54
+
55
+
56
+ ### Issue invoice
57
+
58
+ Monthly invoices are generated with `invoice create --monthly` sub command. Target month is optional. Without month, this month including today is the target.
59
+
60
+ ```
61
+ $ luca-deal invoice create --monthly [yyyy m]
62
+ ```
63
+
64
+ Or, any invoice can be created with contract ID. Contract ID is just unique fragment of uuid, listed with `luca-deal invoice create` with no args.
65
+
66
+ ```
67
+ $ luca-deal invoice create 1d3 yyyy m
68
+ ```
69
+
70
+ Invoice conditions are defined by contracts.
71
+
72
+
73
+ ### Send Invoice
74
+
75
+ Invoice is implemented with HTML & ERB. Copy [default template](lib/luca_deal/templates/invoice.html.erb) to `templates/` in the data directory, and customize.
76
+ If you want to send invoices in PDF, you need to install `wkhtmltopdf command separately. Send mail command is as bellows:`
77
+
78
+ ```
79
+ $ luca-deal invoice mail yyyy m
80
+ ```
81
+
82
+
83
+ ### Sales Fee
84
+
85
+ You can also manage revenue share program with Fee object. Setup proper contract structure.
26
86
 
27
87
 
28
88
  ## Data Structure
@@ -5,57 +5,247 @@ require 'date'
5
5
  require 'optparse'
6
6
  require 'luca_deal'
7
7
 
8
- def customer(args = nil, params = {})
9
- case params['mode']
10
- when 'list'
11
- LucaDeal::Customer.new.list_name
12
- when 'create'
13
- if params['name']
14
- id = LucaDeal::Customer.create(name: params['name'])
15
- puts "Successfully generated Customer #{id}" if id
16
- puts 'Edit customer detail.' if id
17
- else
18
- puts 'requires customer\'s name. exit'
19
- exit 1
8
+ class LucaCmd
9
+ class Customer < LucaCmd
10
+ def self.create(args = nil, params = {})
11
+ if args
12
+ id = LucaDeal::Customer.create(name: args[0])
13
+ puts "Successfully generated Customer #{id}" if id
14
+ puts 'Edit customer detail.' if id
15
+ else
16
+ puts 'requires customer\'s name. exit'
17
+ exit 1
18
+ end
19
+ end
20
+
21
+ def self.describe(args = nil, params = {})
22
+ if args.empty?
23
+ list = LucaDeal::Customer.id_completion('')
24
+ puts 'requires customer\'s id. exit'
25
+ list.each { |item| puts " #{item[:id]} #{item[:label]}" }
26
+ exit 1
27
+ else
28
+ list = LucaDeal::Customer.id_completion(args[0])
29
+ case list.length
30
+ when 1
31
+ render(LucaDeal::Customer.new.describe(list.first), params)
32
+ else
33
+ puts 'found multiple contract id. exit'
34
+ list.each { |item| puts " #{item[:id]} #{item[:label]}" }
35
+ exit 1
36
+ end
37
+ end
38
+ end
39
+
40
+ def self.delete(args = nil, params = {})
41
+ if args.empty?
42
+ list = LucaDeal::Customer.id_completion('')
43
+ puts 'requires customer\'s id. exit'
44
+ list.each { |item| puts " #{item[:id]} #{item[:label]}" }
45
+ exit 1
46
+ else
47
+ list = LucaDeal::Customer.id_completion(args[0])
48
+ case list.length
49
+ when 1
50
+ id = LucaDeal::Customer.delete(list.first)
51
+ else
52
+ puts 'found multiple customer\'s id. exit'
53
+ list.each { |item| puts " #{item[:id]} #{item[:label]}" }
54
+ exit 1
55
+ end
56
+ end
57
+ end
58
+
59
+ def self.list(args = nil, params = {})
60
+ render(LucaDeal::Customer.new.list_name, params)
20
61
  end
21
- else
22
- puts 'invalid option. --help for usage'
23
- exit 1
24
62
  end
25
- end
26
63
 
27
- def contract(args = nil, params = {})
28
- case params['mode']
29
- when 'create'
30
- if params['customer_id']
31
- id = LucaDeal::Contract.new.generate!(params['customer_id'], params['category'])
32
- puts "Successfully generated Contract #{id}" if id
33
- puts 'Conditions are tentative. Edit contract detail.' if id
34
- else
35
- puts 'requires customer\'s id. exit'
36
- exit 1
64
+ class Contract < LucaCmd
65
+ def self.create(args = nil, params = {})
66
+ if args.empty?
67
+ list = LucaDeal::Customer.id_completion('')
68
+ puts 'requires customer\'s id. exit'
69
+ list.each { |item| puts " #{item[:id]} #{item[:label]}" }
70
+ exit 1
71
+ else
72
+ list = LucaDeal::Customer.id_completion(args[0])
73
+ case list.length
74
+ when 1
75
+ id = LucaDeal::Contract.new.generate!(list.first, params['category'])
76
+ puts "Successfully generated Contract #{id}" if id
77
+ puts 'Conditions are tentative. Edit contract detail.' if id
78
+ else
79
+ puts 'found multiple customer\'s id. exit'
80
+ list.each { |item| puts " #{item[:id]} #{item[:label]}" }
81
+ exit 1
82
+ end
83
+ end
84
+ end
85
+
86
+ def self.describe(args = nil, params = {})
87
+ if args.empty?
88
+ list = LucaDeal::Contract.id_completion('', label: 'customer_name')
89
+ puts 'requires contract id. exit'
90
+ list.each { |item| puts " #{item[:id]} #{item[:label]}" }
91
+ exit 1
92
+ else
93
+ list = LucaDeal::Contract.id_completion(args[0])
94
+ case list.length
95
+ when 1
96
+ render(LucaDeal::Contract.new.describe(list.first), params)
97
+ else
98
+ puts 'found multiple contract id. exit'
99
+ list.each { |item| puts " #{item[:id]} #{item[:label]}" }
100
+ exit 1
101
+ end
102
+ end
103
+ end
104
+
105
+ def self.delete(args = nil, params = {})
106
+ if args.empty?
107
+ list = LucaDeal::Contract.id_completion('', label: 'customer_name')
108
+ puts 'requires contract id. exit'
109
+ list.each { |item| puts " #{item[:id]} #{item[:label]}" }
110
+ exit 1
111
+ else
112
+ list = LucaDeal::Contract.id_completion(args[0])
113
+ case list.length
114
+ when 1
115
+ id = LucaDeal::Contract.delete(list.first)
116
+ else
117
+ puts 'found multiple contract id. exit'
118
+ list.each { |item| puts " #{item[:id]} #{item[:label]}" }
119
+ exit 1
120
+ end
121
+ end
37
122
  end
38
- else
39
123
  end
40
- end
41
124
 
42
- def invoice(args = nil, params = {})
43
- date = "#{args[0]}-#{args[1]}-#{args[2] || '1'}" if !args.empty?
44
- case params['mode']
45
- when 'monthly'
46
- LucaDeal::Invoice.new(date).monthly_invoice
47
- when 'mail'
48
- LucaDeal::Invoice.new(date).deliver_mail
49
- when 'preview'
50
- LucaDeal::Invoice.new(date).preview_mail
51
- when 'stats'
52
- if args.empty?
53
- date = "#{Date.today.year}-#{Date.today.month}-1"
54
- count = 3
55
- end
56
- LucaDeal::Invoice.new(date).stats(count || 1)
57
- else
58
- puts 'not implemented mode'
125
+ class Invoice < LucaCmd
126
+ def self.create(args = nil, params = {})
127
+ case params['mode']
128
+ when 'monthly'
129
+ date = "#{args[0]}-#{args[1]}-#{args[2] || '1'}" if !args.empty?
130
+ LucaDeal::Invoice.new(date).monthly_invoice
131
+ else
132
+ date = "#{args[1]}-#{args[2]}-#{args[3] || '1'}" if !args.empty?
133
+ list = LucaDeal::Contract.id_completion(args[0] || '', label: 'customer_name')
134
+ if args.length != 3
135
+ puts 'requires contract id & year month. exit'
136
+ list.each { |item| puts " #{item[:id]} #{item[:label]}" }
137
+ exit 1
138
+ else
139
+ case list.length
140
+ when 1
141
+ id = LucaDeal::Invoice.new(date).single_invoice(list.first)
142
+ else
143
+ puts 'found multiple contract id. exit'
144
+ list.each { |item| puts " #{item[:id]} #{item[:label]}" }
145
+ exit 1
146
+ end
147
+ end
148
+ end
149
+ end
150
+
151
+ def self.delete(args = nil, params = {})
152
+ if args
153
+ id = LucaDeal::Invoice.delete(args[0])
154
+ else
155
+ puts 'requires contract id. exit'
156
+ exit 1
157
+ end
158
+ end
159
+
160
+ def self.export(args = nil, _params = nil)
161
+ if args
162
+ args << 28 if args.length == 2 # specify safe last day
163
+ LucaDeal::Invoice.new(args.join('-')).export_json
164
+ else
165
+ LucaDeal::Invoice.new.export_json
166
+ end
167
+ end
168
+
169
+ def self.list(args = nil, params = {})
170
+ date = "#{args[0]}-#{args[1]}-#{args[2] || '1'}" if !args.empty?
171
+ if args.empty?
172
+ date = "#{Date.today.year}-#{Date.today.month}-1"
173
+ count = 3
174
+ end
175
+ if params[:html]
176
+ LucaDeal::Invoice.new(date).preview_stdout
177
+ elsif params[:mail]
178
+ LucaDeal::Invoice.new(date).stats_email
179
+ else
180
+ render(LucaDeal::Invoice.new(date).stats(count || 1), params)
181
+ end
182
+ end
183
+
184
+ def self.mail(args = nil, params = {})
185
+ date = "#{args[0]}-#{args[1]}-#{args[2] || '1'}" if !args.empty?
186
+ case params['mode']
187
+ when 'preview'
188
+ LucaDeal::Invoice.new(date).preview_mail
189
+ else
190
+ LucaDeal::Invoice.new(date).deliver_mail
191
+ end
192
+ end
193
+ end
194
+
195
+ class Fee < LucaCmd
196
+ def self.create(args = nil, params = {})
197
+ case params['mode']
198
+ when 'monthly'
199
+ date = "#{args[0]}-#{args[1]}-#{args[2] || '1'}" if !args.empty?
200
+ LucaDeal::Fee.new(date).monthly_fee
201
+ else
202
+ puts "not implemented yet"
203
+ exit 1
204
+ end
205
+ end
206
+
207
+ def self.delete(args = nil, params = {})
208
+ if args
209
+ id = LucaDeal::Fee.delete(args[0])
210
+ else
211
+ puts 'requires contract id. exit'
212
+ exit 1
213
+ end
214
+ end
215
+
216
+ def self.list(args = nil, params = {})
217
+ date = "#{args[0]}-#{args[1]}-#{args[2] || '1'}" if !args.empty?
218
+ if args.empty?
219
+ date = "#{Date.today.year}-#{Date.today.month}-1"
220
+ count = 3
221
+ end
222
+ if params[:html]
223
+ LucaDeal::Fee.new(date).preview_stdout
224
+ else
225
+ render(LucaDeal::Fee.new(date).stats(count || 1), params)
226
+ end
227
+ end
228
+
229
+ def self.mail(args = nil, params = {})
230
+ date = "#{args[0]}-#{args[1]}-#{args[2] || '1'}" if !args.empty?
231
+ case params['mode']
232
+ when 'preview'
233
+ LucaDeal::Fee.new(date).preview_mail
234
+ else
235
+ LucaDeal::Fee.new(date).deliver_mail
236
+ end
237
+ end
238
+ end
239
+
240
+ def self.render(dat, params)
241
+ case params[:output]
242
+ when 'json'
243
+ puts JSON.dump(dat)
244
+ when 'nu'
245
+ LucaSupport::View.nushell(YAML.dump(dat))
246
+ else
247
+ puts YAML.dump(dat)
248
+ end
59
249
  end
60
250
  end
61
251
 
@@ -65,54 +255,171 @@ end
65
255
 
66
256
  LucaRecord::Base.valid_project?
67
257
  cmd = ARGV.shift
258
+ params = {}
68
259
 
69
260
  case cmd
70
- when 'customer'
71
- params = {}
72
- OptionParser.new do |opt|
73
- opt.banner = 'Usage: luca-deal customer [options]'
74
- opt.on('--list', 'list all customers') { |v| params['mode'] = 'list' }
75
- opt.on('--create CustomerName', 'register new customer') do |v|
76
- params['mode'] = 'create'
77
- params['name'] = v
261
+ when /customers?/
262
+ subcmd = ARGV.shift
263
+ case subcmd
264
+ when 'create'
265
+ OptionParser.new do |opt|
266
+ opt.banner = 'Usage: luca-deal customers create CustomerName'
267
+ args = opt.parse(ARGV)
268
+ LucaCmd::Customer.create(args, params)
78
269
  end
79
- args = opt.parse(ARGV)
80
- customer(args, params)
270
+ when 'list'
271
+ OptionParser.new do |opt|
272
+ opt.banner = 'Usage: luca-deal customers list [options]'
273
+ opt.on('--nu', 'show table in nushell') { |_v| params[:output] = 'nu' }
274
+ opt.on('-o', '--output VAL', 'output serialized data') { |v| params[:output] = v }
275
+ args = opt.parse(ARGV)
276
+ LucaCmd::Customer.list(args, params)
277
+ end
278
+ when 'describe'
279
+ OptionParser.new do |opt|
280
+ opt.banner = 'Usage: luca-deal customers describe [options] customer_id'
281
+ opt.on('--nu', 'show table in nushell') { |_v| params[:output] = 'nu' }
282
+ opt.on('-o', '--output VAL', 'output serialized data') { |v| params[:output] = v }
283
+ args = opt.parse(ARGV)
284
+ LucaCmd::Customer.describe(args, params)
285
+ end
286
+ when 'delete'
287
+ LucaCmd::Customer.delete(ARGV)
288
+ else
289
+ puts 'Proper subcommand needed.'
290
+ puts
291
+ puts 'Usage: luca-deal customer[s] subcommands [--help|options]'
292
+ puts ' create'
293
+ puts ' list'
294
+ puts ' describe: show customer with contracts info'
295
+ puts ' delete'
296
+ exit 1
81
297
  end
82
- when 'contract'
83
- params = {}
84
- OptionParser.new do |opt|
85
- opt.banner = 'Usage: luca-deal contract [options]'
86
- opt.on('--create CustomerId', 'register new contract') do |v|
87
- params['mode'] = 'create'
88
- params['customer_id'] = v
298
+ when /contracts?/
299
+ subcmd = ARGV.shift
300
+ case subcmd
301
+ when 'create'
302
+ OptionParser.new do |opt|
303
+ opt.banner = 'Usage: luca-deal contracts create [options] CustomerId'
304
+ opt.on('--salesfee', 'create contract as sales fee definition') do |_v|
305
+ params['category'] = 'sales_fee'
306
+ end
307
+ args = opt.parse(ARGV)
308
+ LucaCmd::Contract.create(args, params)
89
309
  end
90
- opt.on('--salesfee', 'create contract as sales fee definition') do |_v|
91
- params['category'] = 'sales_fee'
310
+ when 'describe'
311
+ OptionParser.new do |opt|
312
+ opt.banner = 'Usage: luca-deal contracts describe [options] customer_id'
313
+ opt.on('--nu', 'show table in nushell') { |_v| params[:output] = 'nu' }
314
+ opt.on('-o', '--output VAL', 'output serialized data') { |v| params[:output] = v }
315
+ args = opt.parse(ARGV)
316
+ LucaCmd::Contract.describe(args, params)
92
317
  end
93
- args = opt.parse(ARGV)
94
- contract(args, params)
318
+ when 'delete'
319
+ LucaCmd::Contract.delete(ARGV)
320
+ else
321
+ puts 'Proper subcommand needed.'
322
+ puts
323
+ puts 'Usage: luca-deal contract[s] subcommand [--help|options]'
324
+ puts ' create'
325
+ puts ' describe: show contract with puroducts or items info'
326
+ puts ' delete'
327
+ exit 1
95
328
  end
96
- when 'invoice'
97
- params = {}
98
- OptionParser.new do |opt|
99
- opt.banner = 'Usage: luca-deal invoice [options] year month [date]'
100
- opt.on('--monthly', 'generate monthly data') { |v| params['mode'] = 'monthly' }
101
- opt.on('--mail', 'send to customers') { |v| params['mode'] = 'mail' }
102
- opt.on('--preview', 'send to preview user') { |v| params['mode'] = 'preview' }
103
- opt.on('--stats', 'list invoices') { |v| params['mode'] = 'stats' }
104
- args = opt.parse(ARGV)
105
- invoice(args, params)
329
+ when 'export'
330
+ LucaCmd::Invoice.export(ARGV)
331
+ when /invoices?/, 'i'
332
+ subcmd = ARGV.shift
333
+ case subcmd
334
+ when 'create'
335
+ OptionParser.new do |opt|
336
+ opt.banner = 'Usage: luca-deal invoices create [options] --monthly|contract_id year month [date]'
337
+ opt.on('--monthly', 'generate monthly data') { |_v| params['mode'] = 'monthly' }
338
+ args = opt.parse(ARGV)
339
+ LucaCmd::Invoice.create(args, params)
340
+ end
341
+ when 'delete'
342
+ LucaCmd::Invoice.delete(ARGV)
343
+ when 'list'
344
+ OptionParser.new do |opt|
345
+ opt.banner = 'Usage: luca-deal invoices list [options] year month [date]'
346
+ opt.on('--nu', 'show table in nushell') { |_v| params[:output] = 'nu' }
347
+ opt.on('-o', '--output VAL', 'output serialized data') { |v| params[:output] = v }
348
+ opt.on('--html', 'output html invoices') { |_v| params[:html] = 'monthly' }
349
+ opt.on('--mail', 'send payment list by email') { |_v| params[:mail] = true }
350
+ args = opt.parse(ARGV)
351
+ LucaCmd::Invoice.list(args, params)
352
+ end
353
+ when 'mail'
354
+ OptionParser.new do |opt|
355
+ opt.banner = 'Usage: luca-deal invoices mail [options] year month [date]'
356
+ opt.on('--preview', 'send to preview user') { |_v| params['mode'] = 'preview' }
357
+ args = opt.parse(ARGV)
358
+ LucaCmd::Invoice.mail(args, params)
359
+ end
360
+ else
361
+ puts 'Proper subcommand needed.'
362
+ puts
363
+ puts 'Usage: luca-deal invoices subcommand [--help|options]'
364
+ puts ' create'
365
+ puts ' delete'
366
+ puts ' list'
367
+ puts ' mail: send mail with invoice'
368
+ exit 1
106
369
  end
107
370
  when 'new'
108
371
  params = {}
109
372
  OptionParser.new do |opt|
373
+ opt.banner = 'Usage: luca-deal new DIR'
110
374
  args = opt.parse(ARGV)
111
375
  new_pj(args, params)
112
376
  end
377
+ when /fee/
378
+ subcmd = ARGV.shift
379
+ case subcmd
380
+ when 'create'
381
+ OptionParser.new do |opt|
382
+ opt.banner = 'Usage: luca-deal fee create [options] year month [date]'
383
+ opt.on('--monthly', 'generate monthly data') { |_v| params['mode'] = 'monthly' }
384
+ args = opt.parse(ARGV)
385
+ LucaCmd::Fee.create(args, params)
386
+ end
387
+ when 'delete'
388
+ LucaCmd::Fee.delete(ARGV)
389
+ when 'list'
390
+ OptionParser.new do |opt|
391
+ opt.banner = 'Usage: luca-deal fee list [options] year month [date]'
392
+ opt.on('--nu', 'show table in nushell') { |_v| params[:output] = 'nu' }
393
+ opt.on('-o', '--output VAL', 'output serialized data') { |v| params[:output] = v }
394
+ opt.on('--html', 'output html invoices') { |_v| params[:html] = 'monthly' }
395
+ args = opt.parse(ARGV)
396
+ LucaCmd::Fee.list(args, params)
397
+ end
398
+ when 'mail'
399
+ OptionParser.new do |opt|
400
+ opt.banner = 'Usage: luca-deal fee mail [options] year month [date]'
401
+ opt.on('--preview', 'send to preview user') { |_v| params['mode'] = 'preview' }
402
+ args = opt.parse(ARGV)
403
+ LucaCmd::Fee.mail(args, params)
404
+ end
405
+ else
406
+ puts 'Proper subcommand needed.'
407
+ puts
408
+ puts 'Usage: luca-deal fee subcommand [--help|options]'
409
+ puts ' create'
410
+ puts ' delete'
411
+ puts ' list'
412
+ puts ' mail: send mail with report'
413
+ exit 1
414
+ end
113
415
  else
114
- puts 'Usage: luca-deal sub-command [--help|options]'
115
- puts ' customer'
116
- puts ' contract'
117
- puts ' invoice'
416
+ puts 'Proper subcommand needed.'
417
+ puts
418
+ puts 'Usage: luca-deal subcommand [options]'
419
+ puts ' customers'
420
+ puts ' contracts'
421
+ puts ' invoices'
422
+ puts ' new: initialize project dir'
423
+ puts ' export: puts invoice data for LucaBook import'
424
+ exit 1
118
425
  end