lucadeal 0.4.1 → 0.5.0
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 +4 -4
- data/CHANGELOG.md +11 -0
- data/exe/luca-deal +21 -4
- data/lib/luca_deal/invoice.rb +42 -7
- data/lib/luca_deal/templates/monthly-payment-list.html.erb +23 -0
- data/lib/luca_deal/version.rb +1 -1
- metadata +6 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fa7bf6bd03335ca54d5bf0a1bf2b3e525677ef21e0ea20b009530ba73b310fc9
|
4
|
+
data.tar.gz: 7791dbb5b32566b52ae2bc4209382ca59f1eb95b3f284990f16bd0427f7302ae
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a1b16a74bfdb56bdbda22f1f5003e24f9f5361d361b38c0875a6d8289607328f670a0f10756dc41af7df92b12c1d3b162f15bf9fa68069d175815e13af70bd74
|
7
|
+
data.tar.gz: fce3bf80a9cf60ac5b904e7c51bd7fa83911cd1b5d59377cfb5cdfcaa49adc63fef2d6fdc2fbb8c8d6f0443cd9434ce0dd9eddd8012694439bc0554c818771f2
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,14 @@
|
|
1
|
+
## LucaDeal 0.5.0
|
2
|
+
|
3
|
+
* `luca-deal` command now searches valid sub directory.
|
4
|
+
* `luca-deal invoices list` has `--full` option with additional settlement info.
|
5
|
+
* `--mail --full` lists unsettled table.
|
6
|
+
|
7
|
+
## LucaDeal 0.4.2
|
8
|
+
|
9
|
+
* `luca-deal custoer|invoice|fee list`, `luca-deal reports balance` supports interactive `--explore` w/nushell.
|
10
|
+
* `luca-deal invoices settle` checks already settled invoices and renamed customer.
|
11
|
+
|
1
12
|
## LucaDeal 0.4.1
|
2
13
|
|
3
14
|
* Limit LucaRecord dependency '>= 0.5.4'
|
data/exe/luca-deal
CHANGED
@@ -1,6 +1,16 @@
|
|
1
1
|
#!/usr/bin/ruby
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
|
+
unless Dir.exist?('data') || ARGV[0] == 'new'
|
5
|
+
target = 'customers'
|
6
|
+
Dir.glob('*').reject { |f| File.symlink?(f) }
|
7
|
+
.find { |f| File.directory?("#{f}/data/#{target}") }.tap do |d|
|
8
|
+
abort "No valid data directory, exit..." if d.nil?
|
9
|
+
|
10
|
+
Dir.chdir(d)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
4
14
|
require 'date'
|
5
15
|
require 'optparse'
|
6
16
|
require 'luca_deal'
|
@@ -131,7 +141,7 @@ class LucaCmd
|
|
131
141
|
LucaDeal::NoInvoice.new(date).monthly_invoice
|
132
142
|
LucaDeal::Fee.new(date).monthly_fee if params[:fee]
|
133
143
|
if params[:mail]
|
134
|
-
LucaDeal::Invoice.new(date).stats_email
|
144
|
+
LucaDeal::Invoice.new(date).stats_email(3, mode: 'full')
|
135
145
|
end
|
136
146
|
else
|
137
147
|
date = "#{args[1]}-#{args[2]}-#{args[3] || '1'}" if !args.empty?
|
@@ -178,9 +188,9 @@ class LucaCmd
|
|
178
188
|
count = 3
|
179
189
|
end
|
180
190
|
if params[:mail]
|
181
|
-
LucaDeal::Invoice.new(date).stats_email
|
191
|
+
LucaDeal::Invoice.new(date).stats_email(3, mode: params[:mode])
|
182
192
|
else
|
183
|
-
render(LucaDeal::Invoice.new(date).stats(count || 1), params)
|
193
|
+
render(LucaDeal::Invoice.new(date).stats(count || 1, mode: params[:mode]), params)
|
184
194
|
end
|
185
195
|
end
|
186
196
|
|
@@ -274,7 +284,9 @@ class LucaCmd
|
|
274
284
|
when 'json'
|
275
285
|
puts JSON.dump(dat)
|
276
286
|
when 'nu'
|
277
|
-
LucaSupport::View.nushell(dat)
|
287
|
+
LucaSupport::View.nushell(dat, :expand)
|
288
|
+
when 'explore'
|
289
|
+
LucaSupport::View.nushell(dat, :explore)
|
278
290
|
when 'csv'
|
279
291
|
str = CSV.generate(String.new, col_sep: "\t") do |row|
|
280
292
|
row << dat.first.keys
|
@@ -309,6 +321,7 @@ when /customers?/
|
|
309
321
|
OptionParser.new do |opt|
|
310
322
|
opt.banner = 'Usage: luca-deal customers list [options]'
|
311
323
|
opt.on('--nu', 'show table in nushell') { |_v| params[:output] = 'nu' }
|
324
|
+
opt.on('--explore', 'explore table in nushell') { |_v| params[:output] = 'explore' }
|
312
325
|
opt.on('-o', '--output VAL', 'output serialized data') { |v| params[:output] = v }
|
313
326
|
args = opt.parse(ARGV)
|
314
327
|
LucaCmd::Customer.list(args, params)
|
@@ -384,8 +397,10 @@ when /invoices?/, 'i'
|
|
384
397
|
OptionParser.new do |opt|
|
385
398
|
opt.banner = 'Usage: luca-deal invoices list [options] year month [date]'
|
386
399
|
opt.on('--nu', 'show table in nushell') { |_v| params[:output] = 'nu' }
|
400
|
+
opt.on('--explore', 'explore table in nushell') { |_v| params[:output] = 'explore' }
|
387
401
|
opt.on('-o', '--output VAL', 'output serialized data') { |v| params[:output] = v }
|
388
402
|
opt.on('--mail', 'send payment list by email') { |_v| params[:mail] = true }
|
403
|
+
opt.on('--full', 'add settlement info') { |_v| params[:mode] = 'full' }
|
389
404
|
args = opt.parse(ARGV)
|
390
405
|
LucaCmd::Invoice.list(args, params)
|
391
406
|
end
|
@@ -432,6 +447,7 @@ when /reports?/, 'r'
|
|
432
447
|
OptionParser.new do |opt|
|
433
448
|
opt.banner = 'Usage: luca-deal r[eports] balance [options] [year month]'
|
434
449
|
opt.on('--nu', 'show table in nushell') { |_v| params[:output] = 'nu' }
|
450
|
+
opt.on('--explore', 'explore table in nushell') { |_v| params[:output] = 'explore' }
|
435
451
|
opt.on('-o', '--output VAL', 'output serialized data') { |v| params[:output] = v }
|
436
452
|
opt.on('--detail', 'show detail info') { |_v| params[:detail] = true }
|
437
453
|
opt.on('--force-due', 'respect due date over actual payment') { |_v| params[:due] = true }
|
@@ -470,6 +486,7 @@ when /fee/
|
|
470
486
|
OptionParser.new do |opt|
|
471
487
|
opt.banner = 'Usage: luca-deal fee list [options] year month [date]'
|
472
488
|
opt.on('--nu', 'show table in nushell') { |_v| params[:output] = 'nu' }
|
489
|
+
opt.on('--explore', 'explore table in nushell') { |_v| params[:output] = 'explore' }
|
473
490
|
opt.on('-o', '--output VAL', 'output serialized data') { |v| params[:output] = v }
|
474
491
|
opt.on('--html', 'output html invoices') { |_v| params[:html] = 'monthly' }
|
475
492
|
args = opt.parse(ARGV)
|
data/lib/luca_deal/invoice.rb
CHANGED
@@ -150,7 +150,11 @@ module LucaDeal
|
|
150
150
|
#
|
151
151
|
def self.settle(io, payment_terms = 1)
|
152
152
|
customers = {}.tap do |h|
|
153
|
-
Customer.all.each
|
153
|
+
Customer.all.each do |c|
|
154
|
+
LucaSupport::Code.take_history(c, 'name').each do |name|
|
155
|
+
h[name] = c
|
156
|
+
end
|
157
|
+
end
|
154
158
|
end
|
155
159
|
contracts = {}.tap do |h|
|
156
160
|
Contract.all.each { |c| h[c['customer_id']] ||= []; h[c['customer_id']] << c }
|
@@ -181,6 +185,11 @@ module LucaDeal
|
|
181
185
|
if Regexp.new("^LucaBook/#{j['id']}").match invoice.dig('settled', 'id')||''
|
182
186
|
break
|
183
187
|
end
|
188
|
+
next if 0 >= [
|
189
|
+
invoice.dig('subtotal', 0, 'items'),
|
190
|
+
invoice.dig('subtotal', 0, 'tax'),
|
191
|
+
invoice.dig('settled', 'amount')
|
192
|
+
].compact.sum
|
184
193
|
|
185
194
|
invoice['settled'] = {
|
186
195
|
'id' => "LucaBook/#{j['id']}",
|
@@ -212,7 +221,7 @@ module LucaDeal
|
|
212
221
|
# total: 100000
|
213
222
|
# tax: 10000
|
214
223
|
#
|
215
|
-
def stats(count = 1)
|
224
|
+
def stats(count = 1, mode: nil)
|
216
225
|
[].tap do |collection|
|
217
226
|
scan_date = @date.next_month
|
218
227
|
count.times do
|
@@ -226,8 +235,13 @@ module LucaDeal
|
|
226
235
|
'subtotal' => amount,
|
227
236
|
'tax' => tax,
|
228
237
|
'due' => invoice.dig('due_date'),
|
229
|
-
'mail' => invoice.dig('status')&.select { |a| a.keys.include?('mail_delivered') }&.first
|
230
|
-
}
|
238
|
+
'mail' => invoice.dig('status')&.select { |a| a.keys.include?('mail_delivered') }&.first,
|
239
|
+
}.tap do |r|
|
240
|
+
if mode == 'full'
|
241
|
+
r['settled'] = invoice.dig('settled', 'amount')
|
242
|
+
r['settle_date'] = invoice.dig('settled', 'date')
|
243
|
+
end
|
244
|
+
end
|
231
245
|
end
|
232
246
|
stat['issue_date'] = scan_date.to_s
|
233
247
|
stat['count'] = stat['records'].count
|
@@ -241,14 +255,25 @@ module LucaDeal
|
|
241
255
|
|
242
256
|
# send payment list to preview address or from address.
|
243
257
|
#
|
244
|
-
def stats_email
|
258
|
+
def stats_email(count = 3, mode: nil)
|
245
259
|
{}.tap do |res|
|
246
|
-
stats(
|
260
|
+
stats(count, mode: mode).each.with_index(1) do |stat, i|
|
247
261
|
stat['records'].each do |record|
|
248
262
|
res[record['customer']] ||= {}
|
249
263
|
res[record['customer']]['customer_name'] ||= record['customer']
|
250
|
-
res[record['customer']]["amount#{i}"] ||= record['subtotal']
|
264
|
+
res[record['customer']]["amount#{i}"] ||= record['subtotal'].to_s
|
251
265
|
res[record['customer']]["tax#{i}"] ||= record['tax']
|
266
|
+
next if mode != 'full' || ! record['settled']
|
267
|
+
|
268
|
+
diff = ['subtotal', 'tax', 'settled'].map { |k| record[k] }.compact.sum
|
269
|
+
mark = if diff == 0
|
270
|
+
'[S]'
|
271
|
+
elsif diff > 0
|
272
|
+
'[P]'
|
273
|
+
else
|
274
|
+
'[O]'
|
275
|
+
end
|
276
|
+
res[record['customer']]["amount#{i}"].insert(0, mark)
|
252
277
|
end
|
253
278
|
if i == 1
|
254
279
|
@issue_date = stat['issue_date']
|
@@ -260,6 +285,16 @@ module LucaDeal
|
|
260
285
|
@invoices = res.values
|
261
286
|
end
|
262
287
|
@company = CONFIG.dig('company', 'name')
|
288
|
+
@legend = if mode == 'full'
|
289
|
+
'[S] Settled, [P] Partially settled, [O] Overpaid'
|
290
|
+
else
|
291
|
+
''
|
292
|
+
end
|
293
|
+
@unsettled = if mode == 'full'
|
294
|
+
self.class.report(@date)
|
295
|
+
else
|
296
|
+
[]
|
297
|
+
end
|
263
298
|
|
264
299
|
mail = Mail.new
|
265
300
|
mail.to = CONFIG.dig('mail', 'preview') || CONFIG.dig('mail', 'from')
|
@@ -50,5 +50,28 @@
|
|
50
50
|
</tr>
|
51
51
|
</tbody>
|
52
52
|
</table>
|
53
|
+
<div style="margin: 1em 0"><%= @legend %></div>
|
54
|
+
|
55
|
+
<% if ! @unsettled.empty? %>
|
56
|
+
<h3 style="margin: 1em 0">Unsettled</h3>
|
57
|
+
<table>
|
58
|
+
<thead>
|
59
|
+
<tr>
|
60
|
+
<th>#</th>
|
61
|
+
<th>Customer</th>
|
62
|
+
<th>Balance</th>
|
63
|
+
</tr>
|
64
|
+
</thead>
|
65
|
+
<tbody>
|
66
|
+
<% @unsettled.each.with_index(1) do |record, i| %>
|
67
|
+
<tr>
|
68
|
+
<th><%= i %></th>
|
69
|
+
<td><%= record['customer'] %></td>
|
70
|
+
<td><%= record['unsettled'] %></td>
|
71
|
+
</tr>
|
72
|
+
<% end %>
|
73
|
+
</tbody>
|
74
|
+
</table>
|
75
|
+
<% end %>
|
53
76
|
</body>
|
54
77
|
</html>
|
data/lib/luca_deal/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: lucadeal
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Chuma Takahiro
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-04-
|
11
|
+
date: 2023-04-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: lucarecord
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 0.
|
19
|
+
version: 0.6.0
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: 0.
|
26
|
+
version: 0.6.0
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: bundler
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -111,14 +111,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
111
111
|
requirements:
|
112
112
|
- - ">="
|
113
113
|
- !ruby/object:Gem::Version
|
114
|
-
version:
|
114
|
+
version: 3.0.0
|
115
115
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
116
116
|
requirements:
|
117
117
|
- - ">="
|
118
118
|
- !ruby/object:Gem::Version
|
119
119
|
version: '0'
|
120
120
|
requirements: []
|
121
|
-
rubygems_version: 3.
|
121
|
+
rubygems_version: 3.4.10
|
122
122
|
signing_key:
|
123
123
|
specification_version: 4
|
124
124
|
summary: Deal with contracts
|