aub-payroll 0.1.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,75 @@
1
+ module AUB
2
+ module Payroll
3
+ module SummaryFile
4
+ class HTMLGenerator
5
+
6
+ def initialize(company_info:, payroll_info:, transactions:)
7
+ @company_info = company_info
8
+ @payroll_info = payroll_info
9
+ @transactions = transactions
10
+ end
11
+
12
+ def generate
13
+ Dir.mktmpdir do |dir|
14
+ Dir.chdir(dir) do
15
+ render 'body.slim', 'body.html'
16
+ render 'header.slim', 'header.html'
17
+ render 'footer.slim', 'footer.html'
18
+ render 'style.scss', 'style.css'
19
+ render 'clear.css', with: :copy
20
+ render 'footer.js', with: :copy
21
+ render 'underscore-min.js', with: :copy, from: :vendor
22
+ yield
23
+ end
24
+ end
25
+ end
26
+
27
+ attr_reader :company_info, :payroll_info, :transactions
28
+
29
+ private
30
+
31
+ def format_currency(number)
32
+ whole, decimal = format('%.2f', number).split('.')
33
+ whole.split(//).reverse.in_groups_of(3).map(&:reverse).map(&:join).reverse.join(',') + ".#{decimal}"
34
+ end
35
+
36
+ def template_file_path(name)
37
+ GEM_ROOT + "/lib/aub/payroll/summary_file/templates/#{name}"
38
+ end
39
+
40
+ def render_tilt_template(template_path)
41
+ Tilt.new(template_path).render(self)
42
+ end
43
+
44
+ def render(template, output = template, with: :tilt, from: :templates)
45
+ source_path = resolve_source(from, template)
46
+ body = render_body(source_path, with)
47
+
48
+ File.open(output, 'w') { |fh| fh.write(body) }
49
+ end
50
+
51
+ def render_body(source_path, with)
52
+ case with
53
+ when :tilt
54
+ render_tilt_template(source_path)
55
+ when :copy
56
+ File.read(source_path)
57
+ else
58
+ raise "unhandled engine: #{with.inspect}"
59
+ end
60
+ end
61
+
62
+ def resolve_source(from, template)
63
+ case from
64
+ when :templates
65
+ template_file_path(template)
66
+ when :vendor
67
+ GEM_ROOT + "/vendor/#{template}"
68
+ else
69
+ raise "unhandled source: #{from.inspect}"
70
+ end
71
+ end
72
+ end
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,18 @@
1
+ module AUB
2
+ module Payroll
3
+ module SummaryFile
4
+ class PayrollInfo
5
+ include PhModel
6
+
7
+ attribute :period_start
8
+ attribute :period_end
9
+ attribute :pay_date
10
+ attribute :total
11
+
12
+ validates :period_start, :period_end, :pay_date, presence: true
13
+ validates :total, presence: true, numericality: true
14
+
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,75 @@
1
+ doctype html
2
+ html
3
+ head
4
+ link(rel='stylesheet' type='text/css' href='style.css')
5
+ body.body
6
+
7
+ div
8
+ table(cellpadding="0" cellspacing="0")
9
+ thead
10
+ tr
11
+ td.spacer  
12
+ th.employee-name Employee's Name
13
+ th.account-number Savings Account No.
14
+ th.amount Amount
15
+ td.spacer  
16
+ tbody
17
+ - transactions.each do |transaction|
18
+ tr
19
+ td.spacer  
20
+ td.employee-name
21
+ = transaction.employee_name
22
+ td.account-number
23
+ = transaction.account_number
24
+ td.amount
25
+ = format_currency(transaction.amount)
26
+ td.spacer  
27
+ tfoot
28
+ tr
29
+ td(colspan=5)  
30
+
31
+ table.summary(cellpadding="0" cellspacing="0")
32
+ tbody
33
+ tr
34
+ td.spacer  
35
+ td.total-employees
36
+ ' Total No. Of Employees: #{transactions.length}
37
+ td.account-number
38
+ td.amount
39
+ span.label Total:
40
+ ' #{format_currency(payroll_info.total)}
41
+ td.spacer  
42
+ tr
43
+ td
44
+ td
45
+ td
46
+ td.amount
47
+ = '='*20
48
+
49
+ .nothing-follows
50
+ ' #{'-'*40} NOTHING FOLLOWS #{'-'*40}
51
+
52
+ div.signatures
53
+ table(cellspacing="0" cellpadding="0")
54
+ tr
55
+ td.prepared-by
56
+ 'Prepared By:
57
+
58
+ div.signature-line
59
+ div.name #{company_info.prepared_by_name_1}
60
+ div.spacer
61
+
62
+ div.signature-line
63
+ div.name #{company_info.prepared_by_name_2}
64
+ div.name Authorized Signature
65
+ td
66
+ td.checked-by
67
+ 'Checked By:
68
+
69
+ div.signature-line
70
+ div.name #{company_info.checked_by_name_1}
71
+ div.spacer
72
+
73
+ div.signature-line
74
+ div.name #{company_info.checked_by_name_2}
75
+ div.name Authorized Signature
@@ -0,0 +1,74 @@
1
+ /* Global Defaults */
2
+ html, body {
3
+ margin: 0px;
4
+ padding: 0px;
5
+ border: 0px;
6
+ }
7
+
8
+ body {
9
+ font: 1em/1.25 Arial, Helvetica, sans-serif;
10
+ }
11
+
12
+ /* Headlines */
13
+ h1, h2, h3, h4, h5, h6 {
14
+ margin: 0;
15
+ padding: 0;
16
+ font-weight: normal;
17
+ font-family: Arial, Helvetica, sans-serif;
18
+ }
19
+
20
+ /* Text Styles */
21
+ p, th, td, li, dd, dt, ul, ol, blockquote, q, acronym, abbr, a, input, select, textarea {
22
+ margin: 0;
23
+ padding: 0;
24
+ font: normal normal normal 1em/1.25 Arial, Helvetica, sans-serif;
25
+ }
26
+
27
+ blockquote {
28
+ margin: 1.25em;
29
+ padding: 1.25em
30
+ }
31
+
32
+ q {
33
+ font-style: italic;
34
+ }
35
+
36
+ acronym, abbr {
37
+ cursor: help;
38
+ border-bottom: 1px dashed;
39
+ }
40
+
41
+ small {
42
+ font-size: .85em;
43
+ }
44
+
45
+ big {
46
+ font-size: 1.2em;
47
+ }
48
+
49
+ /* Links and Images */
50
+ a, a:link, a:visited, a:active, a:hover {
51
+ text-decoration: underline;
52
+ }
53
+
54
+ img {
55
+ border: none;
56
+ }
57
+
58
+ /* Tables */
59
+ table {
60
+ margin: 0;
61
+ padding: 0;
62
+ border: none;
63
+ }
64
+
65
+ /* Forms */
66
+ form {
67
+ margin: 0;
68
+ padding: 0;
69
+ display: inline;
70
+ }
71
+
72
+ label {
73
+ cursor: pointer;
74
+ }
@@ -0,0 +1,23 @@
1
+ var getQueryParams = function () {
2
+ var query = window.location.search.substring(1); // delete ?
3
+ if (!query) {
4
+ return false;
5
+ }
6
+ return _
7
+ .chain(query.split('&'))
8
+ .map(function (params) {
9
+ var p = params.split('=');
10
+ return [p[0], decodeURIComponent(p[1])];
11
+ })
12
+ .object()
13
+ .value();
14
+ };
15
+
16
+ function substituteQueryParams() {
17
+ var vars = getQueryParams();
18
+ _(['frompage', 'topage', 'page', 'webpage', 'section', 'subsection', 'subsubsection']).each(function(klass) {
19
+ _(document.getElementsByClassName(klass)).each(function(element) {
20
+ element.textContent = vars[klass];
21
+ });
22
+ });
23
+ }
@@ -0,0 +1,10 @@
1
+ doctype html
2
+ html
3
+ head
4
+ link(rel='stylesheet' type='text/css' href='style.css')
5
+ script(src='underscore-min.js' type='application/javascript')
6
+ script(src='footer.js' type='application/javascript')
7
+ body.footer(onload='substituteQueryParams()')
8
+ div.page_number
9
+ span.label Page No.
10
+ span.page
@@ -0,0 +1,15 @@
1
+ doctype html
2
+ html
3
+ head
4
+ link(rel='stylesheet' type='text/css' href='clear.css')
5
+ link(rel='stylesheet' type='text/css' href='style.css')
6
+ body.header
7
+ div.company-info
8
+ div.company-name #{company_info.name}
9
+ div.address1 #{company_info.address1}
10
+ div.address2 #{company_info.address2}
11
+
12
+ div.instruction-text
13
+ div This is to authorize ASIA UNITED BANK, #{company_info.bank_branch} to debit #{format_currency(payroll_info.total)}
14
+ div From #{company_info.name} #{company_info.account_number} for #{payroll_info.period_start} to #{payroll_info.period_end}
15
+ div payroll period, to be credited on #{payroll_info.pay_date} to the individual accounts indicated below.
@@ -0,0 +1,178 @@
1
+ body {
2
+ font-family: monospace;
3
+ margin: 0;
4
+ padding: 0;
5
+
6
+ tr {
7
+ // the following is a black magic style that fixes an issue with THEAD doing weird things
8
+ // on following pages, still needed for v0.12.3
9
+ // see: https://github.com/wkhtmltopdf/wkhtmltopdf/issues/1524
10
+ page-break-inside: avoid;
11
+ }
12
+
13
+ &.header {
14
+ font-size: 8pt;
15
+ margin: 0 20pt;
16
+ padding-bottom: 1pt;
17
+
18
+ .company-info {
19
+ font-weight: bold;
20
+ height: 56pt;
21
+ padding-top: 10pt;
22
+ text-transform: uppercase;
23
+
24
+ .company-name {
25
+ font-size: 2em;
26
+ margin-bottom: 0.25em;
27
+ }
28
+
29
+ .address1 {
30
+ font-size: 1.5em;
31
+ margin-bottom: 0.25em;
32
+ }
33
+
34
+ .address2 {
35
+ font-size: 1.5em;
36
+ font-weight: normal;
37
+ }
38
+ }
39
+
40
+ .instruction-text {
41
+ line-height: 150%;
42
+ }
43
+ }
44
+
45
+ &.footer {
46
+ font-size: 8pt;
47
+ margin: 0 20pt;
48
+
49
+ .page_number {
50
+ margin: 0 auto;
51
+ width: 100pt;
52
+
53
+ .page {
54
+ display: block;
55
+ float: right;
56
+ }
57
+ }
58
+ }
59
+
60
+ &.body {
61
+ $column1-width: 38%;
62
+ $column2-width: 28%;
63
+ $borders: 1pt solid black;
64
+ padding-top: 1px;
65
+ //$column2_width: 33%; # its just the leftover of the columns
66
+
67
+ table {
68
+ border-collapse: collapse;
69
+ width: 100%;
70
+
71
+ th {
72
+ font-weight: normal;
73
+ text-align: left;
74
+ }
75
+
76
+ th,
77
+ td {
78
+ font-family: monospace;
79
+ font-size: 10pt;
80
+ }
81
+
82
+ tbody {
83
+ td {
84
+ padding: 2pt 0;
85
+
86
+ &.amount {
87
+ text-align: right;
88
+ }
89
+ }
90
+ }
91
+
92
+ td.employee-name {
93
+ text-transform: uppercase;
94
+ width: $column1-width;
95
+ }
96
+
97
+ td.account-number {
98
+ width: $column2-width;
99
+ }
100
+
101
+ td.spacer {
102
+ width: 20pt;
103
+ }
104
+
105
+ tfoot {
106
+ tr {
107
+ border-top: $borders;
108
+ }
109
+ }
110
+
111
+ thead {
112
+ th.amount {
113
+ text-align: right;
114
+ }
115
+
116
+ tr {
117
+ border-bottom: $borders;
118
+ border-top: $borders;
119
+
120
+ th,
121
+ td {
122
+ padding: 0.75em 0;
123
+ }
124
+ }
125
+ }
126
+
127
+ &.summary {
128
+ page-break-inside: avoid;
129
+
130
+ td.total-employees {
131
+ width: $column1-width;
132
+ }
133
+
134
+ td.amount {
135
+ .label {
136
+ display: block;
137
+ float: left;
138
+ }
139
+ }
140
+ }
141
+ }
142
+
143
+ .nothing-follows {
144
+ margin: 2pt 0;
145
+ text-align: center;
146
+ }
147
+
148
+ .signatures {
149
+ padding: 0 20px;
150
+
151
+ table {
152
+ text-transform: uppercase;
153
+ width: 100%;
154
+
155
+ .signature-line {
156
+ border-bottom: $borders;
157
+ height: 2em;
158
+ }
159
+
160
+ .name {
161
+ padding: 0.25em 0;
162
+ }
163
+
164
+ .spacer {
165
+ height: 2em;
166
+ }
167
+
168
+ .prepared-by {
169
+ width: 33%;
170
+ }
171
+
172
+ .checked-by {
173
+ width: 33%;
174
+ }
175
+ }
176
+ }
177
+ }
178
+ }