contract_ltd 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +9 -0
- data/Gemfile +4 -0
- data/LICENSE +20 -0
- data/README.md +37 -0
- data/Rakefile +1 -0
- data/bin/console +15 -0
- data/bin/setup +7 -0
- data/contract_ltd.gemspec +29 -0
- data/exe/dividend +6 -0
- data/exe/invoice +6 -0
- data/lib/contract_ltd/base.rb +22 -0
- data/lib/contract_ltd/dividend.rb +31 -0
- data/lib/contract_ltd/dividend.slim +144 -0
- data/lib/contract_ltd/en.yml +14 -0
- data/lib/contract_ltd/invoice.rb +102 -0
- data/lib/contract_ltd/invoice.slim +136 -0
- data/lib/contract_ltd/new.rb +2 -0
- data/lib/contract_ltd/version.rb +4 -0
- data/lib/contract_ltd.rb +80 -0
- metadata +133 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: b9fcfb371074e8baebc094db4dab997ca657abcc
|
4
|
+
data.tar.gz: 62fec7878ca869515e6191cae4e49b8597ec6479
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 7cda08f35a7cf35e246a7779f6850cc524d0b49050f9edd0ad9610c94e811932cf573189bd24779a13da315d0405a64a725a20ac5b4e5eaf5792d46c5e857ed6
|
7
|
+
data.tar.gz: 1d9e656ebea8cf91a4da22c134c5afbad02d7643ec3649f35f2510248b5440a7c472eb37cc0271c89ef4b2d2cfa8d1ea57c9f28af01990a6781d0b44bd3979f4
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2013 Phil Thompson
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
6
|
+
this software and associated documentation files (the "Software"), to deal in
|
7
|
+
the Software without restriction, including without limitation the rights to
|
8
|
+
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
9
|
+
the Software, and to permit persons to whom the Software is furnished to do so,
|
10
|
+
subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
17
|
+
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
18
|
+
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
19
|
+
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
20
|
+
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
Generate PDF invoice, CSV timesheet and dividend certificates from slim templates and ruby code.
|
2
|
+
|
3
|
+
## Install
|
4
|
+
|
5
|
+
Install `phantomjs` then:
|
6
|
+
|
7
|
+
gem install contract_ltd
|
8
|
+
|
9
|
+
|
10
|
+
## New client
|
11
|
+
|
12
|
+
invoice new
|
13
|
+
|
14
|
+
## Usage
|
15
|
+
|
16
|
+
invoice [-f] -months_ago [-i d1,d2,d3,...] [-x d1,d2,d3,...]
|
17
|
+
|
18
|
+
dividend <final|interim> <date paid> <tax year end> <net amount> <company year end>
|
19
|
+
|
20
|
+
## Examples
|
21
|
+
|
22
|
+
Generate timesheet/invoice for last month, worked every week day:
|
23
|
+
|
24
|
+
invoice -1
|
25
|
+
|
26
|
+
Generate timesheet/invoice for current month, worked every day except last week:
|
27
|
+
|
28
|
+
invoice -0 -x 26,27,28,29,30
|
29
|
+
|
30
|
+
Regenerate timesheet/invoice for 2 months ago, only worked a couple of days plus 1 half day
|
31
|
+
|
32
|
+
invoice -f -2 -i 3,4,5am
|
33
|
+
|
34
|
+
Generate a final dividend for 8th August 2015 for £20,000
|
35
|
+
|
36
|
+
dividend 20150810 2015 20000 2016
|
37
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
data/bin/console
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "contract_ltd"
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require "irb"
|
14
|
+
IRB.start
|
15
|
+
|
data/bin/setup
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
require 'base64'
|
3
|
+
|
4
|
+
lib = File.expand_path('../lib', __FILE__)
|
5
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
6
|
+
require 'contract_ltd/version'
|
7
|
+
|
8
|
+
Gem::Specification.new do |spec|
|
9
|
+
spec.name = "contract_ltd"
|
10
|
+
spec.version = ContractLtd::VERSION
|
11
|
+
spec.authors = ["Phil Thompson"]
|
12
|
+
spec.email = Base64.decode64("cGhpbEBlbGVjdHJpY3Zpc2lvbnMuY29t\n")
|
13
|
+
|
14
|
+
spec.summary = 'Generate invoices for contract work and dividend certificates'
|
15
|
+
spec.homepage = 'https://github.com/PhilT/contract_ltd'
|
16
|
+
|
17
|
+
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
18
|
+
spec.bindir = "exe"
|
19
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
20
|
+
spec.require_paths = ["lib"]
|
21
|
+
|
22
|
+
spec.add_dependency 'activesupport'
|
23
|
+
spec.add_dependency 'shrimp'
|
24
|
+
spec.add_dependency 'slim'
|
25
|
+
|
26
|
+
spec.add_development_dependency "bundler", "~> 1.10"
|
27
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
28
|
+
end
|
29
|
+
|
data/exe/dividend
ADDED
data/exe/invoice
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Shrimp.configure do |config|
|
2
|
+
config.format = 'A4'
|
3
|
+
config.margin = '1cm'
|
4
|
+
config.zoom = 1
|
5
|
+
config.orientation = 'portrait'
|
6
|
+
config.rendering_time = 1000
|
7
|
+
config.rendering_timeout = 20000
|
8
|
+
end
|
9
|
+
|
10
|
+
I18n.load_path << "#{File.dirname(__FILE__)}/en.yml"
|
11
|
+
I18n.t('date.formats').each do |key, value|
|
12
|
+
Date::DATE_FORMATS[key] = value
|
13
|
+
end
|
14
|
+
|
15
|
+
def write_pdf(template)
|
16
|
+
html = Slim::Template.new(template.name('slim')).render(template)
|
17
|
+
File.write(template.name('html'), html)
|
18
|
+
phantom = Shrimp::Phantom.new("file:///#{Dir.pwd}/#{template.name('html')}")
|
19
|
+
phantom.to_pdf(template.filename)
|
20
|
+
FileUtils.rm_f(template.name('html'))
|
21
|
+
end
|
22
|
+
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module ContractLtd
|
2
|
+
class Dividend
|
3
|
+
attr_reader :type, :tax_year_end, :shares, :net, :tax_credit, :gross, :amount, :company_year_end
|
4
|
+
|
5
|
+
def initialize args
|
6
|
+
@name = 'dividend'
|
7
|
+
@type = ARGV[0] == 'final' ? 'Final' : 'Interim'
|
8
|
+
@date_paid = Date.parse(ARGV[1])
|
9
|
+
@tax_year_end = Date.parse(ARGV[2], 4, 5).to_s(:long)
|
10
|
+
@shares = 100
|
11
|
+
@net = ARGV[3].to_f
|
12
|
+
@tax_credit = @net * 0.111111
|
13
|
+
@gross = @net + @tax_credit
|
14
|
+
@amount = @net / @shares
|
15
|
+
@company_year_end = Date.parse(ARGV[4], 2, 28).to_s(:long)
|
16
|
+
end
|
17
|
+
|
18
|
+
def date_paid(format = :long)
|
19
|
+
@date_paid.to_s(format)
|
20
|
+
end
|
21
|
+
|
22
|
+
def name(ext)
|
23
|
+
"#{name}.#{ext}"
|
24
|
+
end
|
25
|
+
|
26
|
+
def filename
|
27
|
+
"#{@name}_#{date_paid(:file)}.pdf"
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
@@ -0,0 +1,144 @@
|
|
1
|
+
doctype html
|
2
|
+
html
|
3
|
+
head
|
4
|
+
meta charset="UTF-8"
|
5
|
+
css:
|
6
|
+
body {
|
7
|
+
margin: 20px 55px;
|
8
|
+
font-family: Arial;
|
9
|
+
font-size: 14px;
|
10
|
+
color: #111;
|
11
|
+
}
|
12
|
+
|
13
|
+
h1 {
|
14
|
+
text-align: center;
|
15
|
+
font-size: larger;
|
16
|
+
}
|
17
|
+
|
18
|
+
h2 {
|
19
|
+
font-size: larger;
|
20
|
+
}
|
21
|
+
|
22
|
+
p, div {
|
23
|
+
overflow: auto;
|
24
|
+
clear: both;
|
25
|
+
padding-bottom: 10px;
|
26
|
+
}
|
27
|
+
|
28
|
+
div {
|
29
|
+
margin: 30px 0;
|
30
|
+
}
|
31
|
+
|
32
|
+
div.sig {
|
33
|
+
margin-top: 100px;
|
34
|
+
}
|
35
|
+
|
36
|
+
table {
|
37
|
+
margin: 0 auto;
|
38
|
+
border-collapse: collapse;
|
39
|
+
}
|
40
|
+
table.bordered th, table.bordered td {
|
41
|
+
border: 1px solid black;
|
42
|
+
margin: 0;
|
43
|
+
padding: 5px;
|
44
|
+
text-align: center;
|
45
|
+
max-width: 90px;
|
46
|
+
}
|
47
|
+
td.underline {
|
48
|
+
border-bottom: 1px solid gray;
|
49
|
+
width: 200px;
|
50
|
+
padding-right: 20px;
|
51
|
+
}
|
52
|
+
|
53
|
+
ul {
|
54
|
+
list-style-type: none;
|
55
|
+
}
|
56
|
+
|
57
|
+
ul, li {
|
58
|
+
margin: 0;
|
59
|
+
padding: 0;
|
60
|
+
}
|
61
|
+
li.left {
|
62
|
+
padding-right: 10px;
|
63
|
+
float: left;
|
64
|
+
}
|
65
|
+
li.right {
|
66
|
+
float: right;
|
67
|
+
}
|
68
|
+
|
69
|
+
body
|
70
|
+
h1 #{type} Dividend Voucher
|
71
|
+
|
72
|
+
h1 ELECTRIC VISIONS LTD
|
73
|
+
|
74
|
+
div
|
75
|
+
ul
|
76
|
+
li.left
|
77
|
+
strong Date Dividend Paid: #{date_paid}
|
78
|
+
li.right
|
79
|
+
strong Tax Year Ending #{tax_year_end}
|
80
|
+
|
81
|
+
div
|
82
|
+
ul
|
83
|
+
li.left
|
84
|
+
strong Name of Payee:
|
85
|
+
li.left
|
86
|
+
strong Phil Thompson
|
87
|
+
|
88
|
+
div
|
89
|
+
table.bordered
|
90
|
+
thead
|
91
|
+
tr
|
92
|
+
th Date
|
93
|
+
th No. of Shares
|
94
|
+
th Dividend per Share
|
95
|
+
th Gross Dividend
|
96
|
+
th Tax Credit
|
97
|
+
th Net Dividend
|
98
|
+
tbody
|
99
|
+
tr
|
100
|
+
td= date_paid(:short)
|
101
|
+
td= shares
|
102
|
+
td= amount.to_s(:currency)
|
103
|
+
td= gross.to_s(:currency)
|
104
|
+
td= tax_credit.to_s(:currency)
|
105
|
+
td= net.to_s(:currency)
|
106
|
+
|
107
|
+
div
|
108
|
+
small Please keep this dividend voucher in a safe place.
|
109
|
+
|
110
|
+
h2 Minutes of a Board meeting to declare #{article} #{type} Dividend
|
111
|
+
|
112
|
+
ul
|
113
|
+
li Date: #{date_paid}
|
114
|
+
li
|
115
|
+
| Address:
|
116
|
+
- if @date_paid < Date.new(2012, 3, 19)
|
117
|
+
| Flat 54, 94 Walm Lane, Willesden Green NW2 4QA
|
118
|
+
- elsif @date_paid < Date.new(2012, 10, 17)
|
119
|
+
| 128 Oakdale Road, London E11 4DL
|
120
|
+
- else
|
121
|
+
| 46 Cypress Grove, Ash Vale GU12 5QN
|
122
|
+
end
|
123
|
+
|
124
|
+
|
125
|
+
p Present: Phil Thompson
|
126
|
+
|
127
|
+
p The meeting was confirmed as being properly convened and quorate. The interest of the directors who are also shareholders in the matter to be considered was noted and
|
128
|
+
|
129
|
+
p IT WAS RESOLVED THAT:
|
130
|
+
|
131
|
+
p Having regard to the level of distributable reserves shown by the company's figures on its remittance advices that the following dividend may be fully met out of distributable reserves and that immediately thereafter the company will remain in a solvent position, able to pay its debts as they fall due and the interests of creditors not prejudiced.
|
132
|
+
|
133
|
+
p An #{type} Dividend of #{amount.to_s(:currency)} per ordinary share be voted in request of the company year ending on the #{company_year_end}
|
134
|
+
|
135
|
+
|
136
|
+
div.sig
|
137
|
+
table
|
138
|
+
tr
|
139
|
+
td.underline
|
140
|
+
td Phil Thompson
|
141
|
+
tr
|
142
|
+
td
|
143
|
+
td Chairman
|
144
|
+
|
@@ -0,0 +1,102 @@
|
|
1
|
+
def file_date(prefix, date, suffix)
|
2
|
+
"#{prefix}_#{date.to_s(:file_no_day)}.#{suffix}"
|
3
|
+
end
|
4
|
+
|
5
|
+
def timesheet_filename(date)
|
6
|
+
file_date("timesheet", date, "csv")
|
7
|
+
end
|
8
|
+
|
9
|
+
def invoice_filename(date)
|
10
|
+
file_date("invoice", date, "pdf")
|
11
|
+
end
|
12
|
+
|
13
|
+
def write_timesheet(date)
|
14
|
+
csv = "Timesheet for Ruby Web Development Services\n"
|
15
|
+
csv += "by Phil Thompson (Electric Visions Ltd)\n"
|
16
|
+
csv += "for #{date.to_s(:month_name_year)}\n\n"
|
17
|
+
csv += "Day,Hours\n"
|
18
|
+
total = 0
|
19
|
+
(date..date.end_of_month.to_date).each do |d|
|
20
|
+
day = working_days(d)
|
21
|
+
total += day if day.is_a?(Float)
|
22
|
+
csv += "#{d.day},#{day * 7.5}\n"
|
23
|
+
end
|
24
|
+
csv += "\n"
|
25
|
+
csv += "Total (hours),#{total * 7.5}\n"
|
26
|
+
csv += "Total (days),#{total}\n"
|
27
|
+
File.open(timesheet_filename(date), 'w') {|f| f.write csv }
|
28
|
+
total
|
29
|
+
end
|
30
|
+
|
31
|
+
class Invoice
|
32
|
+
def initialize(date, total_days)
|
33
|
+
@name = 'invoice'
|
34
|
+
@date = date
|
35
|
+
@total_days = total_days
|
36
|
+
end
|
37
|
+
|
38
|
+
def invoice_num
|
39
|
+
previous_invoice_count = Dir['invoice_*'].size
|
40
|
+
if previous_invoice_count == 0
|
41
|
+
puts "WARNING: NO PREVIOUS INVOICES DETECTED"
|
42
|
+
puts "If this is the first invoice you can ignore this warning"
|
43
|
+
puts "Otherwise make sure previous invoices are in the correct format:"
|
44
|
+
puts " #{timesheet_filename(@date)}"
|
45
|
+
puts " #{invoice_filename(@date)}"
|
46
|
+
end
|
47
|
+
'%03d' % (previous_invoice_count + 1)
|
48
|
+
end
|
49
|
+
|
50
|
+
def month_year
|
51
|
+
@date.to_s(:month_name_year)
|
52
|
+
end
|
53
|
+
|
54
|
+
def todays_date
|
55
|
+
Date.today.to_s(:long)
|
56
|
+
end
|
57
|
+
|
58
|
+
def total_hours
|
59
|
+
@total_days * 7.5
|
60
|
+
end
|
61
|
+
|
62
|
+
def rate(rate = nil)
|
63
|
+
@rate ||= rate
|
64
|
+
end
|
65
|
+
|
66
|
+
def days
|
67
|
+
@total_days
|
68
|
+
end
|
69
|
+
|
70
|
+
def subtotal
|
71
|
+
rate * days
|
72
|
+
end
|
73
|
+
|
74
|
+
def vat
|
75
|
+
subtotal * 0.2
|
76
|
+
end
|
77
|
+
|
78
|
+
def total
|
79
|
+
subtotal + vat
|
80
|
+
end
|
81
|
+
|
82
|
+
def name(ext)
|
83
|
+
"#{@name}.#{ext}"
|
84
|
+
end
|
85
|
+
|
86
|
+
def filename
|
87
|
+
invoice_filename(@date)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def working_days(date)
|
92
|
+
if @days_are_included
|
93
|
+
@days[date.day] || ''
|
94
|
+
else
|
95
|
+
if date.saturday? || date.sunday?
|
96
|
+
''
|
97
|
+
else
|
98
|
+
1.0 - @days[date.day].to_f
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
@@ -0,0 +1,136 @@
|
|
1
|
+
- company = 'Electric Visions Ltd'
|
2
|
+
- email = 'info@electricvisions.com'
|
3
|
+
- address1 = '46 Cypress Grove'
|
4
|
+
- address2 = 'Ash Vale'
|
5
|
+
- address3 = 'GU12 5QN'
|
6
|
+
- company_no = '7369361'
|
7
|
+
- vat_no = '141 5526 34'
|
8
|
+
- client = 'Havas EHS Ltd'
|
9
|
+
- client_address1 = '6 Briset Street'
|
10
|
+
- client_address2 = 'London'
|
11
|
+
- client_address3 = 'EC1M 5NR'
|
12
|
+
- invoice_prefix = 'HAV'
|
13
|
+
- rate(480)
|
14
|
+
- payment_terms = '14'
|
15
|
+
- account_name = 'Phil Thompson'
|
16
|
+
- account_sortcode = '40-04-26'
|
17
|
+
- account_number = '21523996'
|
18
|
+
|
19
|
+
doctype html
|
20
|
+
html
|
21
|
+
head
|
22
|
+
meta charset="utf-8"
|
23
|
+
css:
|
24
|
+
body {
|
25
|
+
margin: 20px 55px;
|
26
|
+
font: normal 12px sans-serif;
|
27
|
+
color: #222;
|
28
|
+
}
|
29
|
+
|
30
|
+
h1 {
|
31
|
+
text-align: center;
|
32
|
+
}
|
33
|
+
|
34
|
+
h2 {
|
35
|
+
font-size: larger;
|
36
|
+
}
|
37
|
+
|
38
|
+
.address {
|
39
|
+
text-align: right;
|
40
|
+
width: 100%;
|
41
|
+
}
|
42
|
+
|
43
|
+
table {
|
44
|
+
width: 100%;
|
45
|
+
}
|
46
|
+
|
47
|
+
thead td {
|
48
|
+
padding-bottom: 10px;
|
49
|
+
}
|
50
|
+
|
51
|
+
td.first {
|
52
|
+
width: 60%;
|
53
|
+
padding-right: 20px;
|
54
|
+
text-align: right;
|
55
|
+
}
|
56
|
+
|
57
|
+
tfoot td {
|
58
|
+
font-weight: bold;
|
59
|
+
}
|
60
|
+
|
61
|
+
ul {
|
62
|
+
list-style-type: none;
|
63
|
+
}
|
64
|
+
ul, li {
|
65
|
+
margin: 0;
|
66
|
+
padding: 0;
|
67
|
+
}
|
68
|
+
ul.account {
|
69
|
+
padding-left: 50px;
|
70
|
+
}
|
71
|
+
|
72
|
+
body
|
73
|
+
h1= "#{company} - Invoice"
|
74
|
+
|
75
|
+
aside.address
|
76
|
+
ul
|
77
|
+
li= address1
|
78
|
+
li= address2
|
79
|
+
li= address3
|
80
|
+
li
|
81
|
+
li= email
|
82
|
+
li Company No. #{company_no}
|
83
|
+
li VAT Registration No. #{vat_no}
|
84
|
+
|
85
|
+
p
|
86
|
+
ul
|
87
|
+
li= client
|
88
|
+
li= client_address1
|
89
|
+
li= client_address2
|
90
|
+
li= client_address3
|
91
|
+
|
92
|
+
ul
|
93
|
+
li
|
94
|
+
| Invoice No:
|
95
|
+
strong #{invoice_prefix}#{invoice_num}
|
96
|
+
li
|
97
|
+
| Date:
|
98
|
+
strong #{todays_date}
|
99
|
+
|
100
|
+
p
|
101
|
+
| To:
|
102
|
+
strong #{client}
|
103
|
+
|
104
|
+
h2 Fees:
|
105
|
+
|
106
|
+
table
|
107
|
+
thead
|
108
|
+
tr
|
109
|
+
td.first Ruby Web Development Services provided to #{client} for #{month_year}
|
110
|
+
td #{rate.to_s(:currency, precision: 0)} * #{"%g days" % days}
|
111
|
+
tbody
|
112
|
+
tr
|
113
|
+
td.first Subtotal
|
114
|
+
td= subtotal.to_s(:currency)
|
115
|
+
tr
|
116
|
+
td.first VAT (20%)
|
117
|
+
td= vat.to_s(:currency)
|
118
|
+
tfoot
|
119
|
+
tr
|
120
|
+
td.first Total
|
121
|
+
td= total.to_s(:currency)
|
122
|
+
|
123
|
+
h2 Payment terms
|
124
|
+
|
125
|
+
p Payment within #{payment_terms} days via money transfer only to the following account:
|
126
|
+
ul.account
|
127
|
+
li
|
128
|
+
| Name:
|
129
|
+
strong #{account_name}
|
130
|
+
li
|
131
|
+
| Sort Code:
|
132
|
+
strong #{account_sortcode}
|
133
|
+
li
|
134
|
+
| Account No:
|
135
|
+
strong #{account_number}
|
136
|
+
|
data/lib/contract_ltd.rb
ADDED
@@ -0,0 +1,80 @@
|
|
1
|
+
require 'bundler/setup'
|
2
|
+
require 'active_support'
|
3
|
+
require 'active_support/time'
|
4
|
+
require 'active_support/core_ext/numeric/conversions'
|
5
|
+
require 'shrimp'
|
6
|
+
require 'slim'
|
7
|
+
require 'contract_ltd/base'
|
8
|
+
require 'contract_ltd/dividend'
|
9
|
+
require 'contract_ltd/invoice'
|
10
|
+
require 'contract_ltd/new'
|
11
|
+
require "contract_ltd/version"
|
12
|
+
|
13
|
+
module ContractLtd
|
14
|
+
def self.invoice
|
15
|
+
if ARGV.empty?
|
16
|
+
puts <<-EOB
|
17
|
+
Create a new invoice.slim template:
|
18
|
+
|
19
|
+
invoice new
|
20
|
+
|
21
|
+
|
22
|
+
Generate a timesheet (CSV) and invoice (PDF) from existing invoice.slim template.
|
23
|
+
|
24
|
+
invoice [-f] [-p] -n [-x|-i [day[am|pm]],[...]]
|
25
|
+
-f - overwrite existing timesheet/invoice
|
26
|
+
-n - generate timesheet/invoice for n months ago (-0 to -12)
|
27
|
+
-x - specify days to exclude (sat/sun excluded anyway)
|
28
|
+
-i - specify days to include
|
29
|
+
am|pm - just the morning or afternoon was taken off (half a day)
|
30
|
+
|
31
|
+
EOB
|
32
|
+
exit
|
33
|
+
end
|
34
|
+
|
35
|
+
# Arguments (other args must be removed before days)
|
36
|
+
@days_are_included = ARGV.delete('-i')
|
37
|
+
@days_are_excluded = ARGV.delete('-x')
|
38
|
+
if @days_are_included && @days_are_excluded
|
39
|
+
puts "Days can only be included or excluded. Not both. Specify -i or -x."
|
40
|
+
exit 1
|
41
|
+
end
|
42
|
+
|
43
|
+
@overwrite = ARGV.delete('-f')
|
44
|
+
month = (0..12).detect {|n| ARGV.delete("-#{n}") }
|
45
|
+
if ARGV.size > 0
|
46
|
+
@days = Hash[*(ARGV.first.split(',').map do |day|
|
47
|
+
[day.to_i, day =~ /am|pm/ ? 0.5 : 1.0]
|
48
|
+
end.flatten)]
|
49
|
+
else
|
50
|
+
@days = []
|
51
|
+
end
|
52
|
+
|
53
|
+
date = month.month.ago.beginning_of_month.to_date
|
54
|
+
if File.exist?(timesheet_filename(date)) || File.exist?(invoice_filename(date))
|
55
|
+
if @overwrite
|
56
|
+
FileUtils.rm_f(timesheet_filename(date))
|
57
|
+
FileUtils.rm_f(invoice_filename(date))
|
58
|
+
else
|
59
|
+
puts "Existing timesheet and/or invoice detected for #{date}"
|
60
|
+
puts "Use -f to overwrite"
|
61
|
+
exit 1
|
62
|
+
end
|
63
|
+
end
|
64
|
+
total_days = write_timesheet(date)
|
65
|
+
write_pdf(Invoice.new(date, total_days))
|
66
|
+
end
|
67
|
+
|
68
|
+
def self.dividend
|
69
|
+
if ARGV.size != 5
|
70
|
+
puts 'dividend <final|interim> <date_paid> <tax_year_end> <net> <year_end>'
|
71
|
+
puts ' date_paid (yyyymmdd)'
|
72
|
+
puts ' tax_year_end (yyyy)'
|
73
|
+
puts ' net amount dividend actually paid out'
|
74
|
+
puts ' year_end company accounts year end (yyyy)'
|
75
|
+
else
|
76
|
+
write_pdf(Dividend.new(ARGV))
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
metadata
ADDED
@@ -0,0 +1,133 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: contract_ltd
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.2.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Phil Thompson
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-09-04 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: activesupport
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: shrimp
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: slim
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: bundler
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '1.10'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '1.10'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rake
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '10.0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '10.0'
|
83
|
+
description:
|
84
|
+
email: phil@electricvisions.com
|
85
|
+
executables:
|
86
|
+
- dividend
|
87
|
+
- invoice
|
88
|
+
extensions: []
|
89
|
+
extra_rdoc_files: []
|
90
|
+
files:
|
91
|
+
- ".gitignore"
|
92
|
+
- Gemfile
|
93
|
+
- LICENSE
|
94
|
+
- README.md
|
95
|
+
- Rakefile
|
96
|
+
- bin/console
|
97
|
+
- bin/setup
|
98
|
+
- contract_ltd.gemspec
|
99
|
+
- exe/dividend
|
100
|
+
- exe/invoice
|
101
|
+
- lib/contract_ltd.rb
|
102
|
+
- lib/contract_ltd/base.rb
|
103
|
+
- lib/contract_ltd/dividend.rb
|
104
|
+
- lib/contract_ltd/dividend.slim
|
105
|
+
- lib/contract_ltd/en.yml
|
106
|
+
- lib/contract_ltd/invoice.rb
|
107
|
+
- lib/contract_ltd/invoice.slim
|
108
|
+
- lib/contract_ltd/new.rb
|
109
|
+
- lib/contract_ltd/version.rb
|
110
|
+
homepage: https://github.com/PhilT/contract_ltd
|
111
|
+
licenses: []
|
112
|
+
metadata: {}
|
113
|
+
post_install_message:
|
114
|
+
rdoc_options: []
|
115
|
+
require_paths:
|
116
|
+
- lib
|
117
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
118
|
+
requirements:
|
119
|
+
- - ">="
|
120
|
+
- !ruby/object:Gem::Version
|
121
|
+
version: '0'
|
122
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
123
|
+
requirements:
|
124
|
+
- - ">="
|
125
|
+
- !ruby/object:Gem::Version
|
126
|
+
version: '0'
|
127
|
+
requirements: []
|
128
|
+
rubyforge_project:
|
129
|
+
rubygems_version: 2.4.5
|
130
|
+
signing_key:
|
131
|
+
specification_version: 4
|
132
|
+
summary: Generate invoices for contract work and dividend certificates
|
133
|
+
test_files: []
|