uktt 0.2.14

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,225 @@
1
+ require 'prawn'
2
+
3
+ # A class to produce a PDF for the Tariff cover and explantion of the columns in the Schedule
4
+ class ExportCoverPdf
5
+ include Prawn::View
6
+
7
+ def initialize(opts = {})
8
+ @opts = opts
9
+
10
+ @margin = [50, 50, 20, 50]
11
+ @footer_height = 30
12
+ @printable_height = 595.28 - (@margin[0] + @margin[2])
13
+ @printable_width = 841.89 - (@margin[1] + @margin[3])
14
+ @base_table_font_size = 8
15
+ @indent_amount = 18
16
+ @document = Prawn::Document.new(
17
+ page_size: 'A4',
18
+ margin: @margin,
19
+ page_layout: :landscape
20
+ )
21
+
22
+ set_fonts
23
+
24
+ bounding_box([0, @printable_height],
25
+ width: @printable_width,
26
+ height: @printable_height - @footer_height) do
27
+ build
28
+ end
29
+
30
+ repeat(:all, dynamic: true) do
31
+ page_footer unless page_number == 1
32
+ end
33
+ end
34
+
35
+ def set_fonts
36
+ font_families.update('OpenSans' => {
37
+ normal: 'vendor/assets/Open_Sans/OpenSans-Regular.ttf',
38
+ italic: 'vendor/assets/Open_Sans/OpenSans-RegularItalic.ttf',
39
+ medium: 'vendor/assets/Open_Sans/OpenSans-SemiBold.ttf',
40
+ medium_italic: 'vendor/assets/Open_Sans/OpenSans-SemiBoldItalic.ttf',
41
+ bold: 'vendor/assets/Open_Sans/OpenSans-Bold.ttf',
42
+ bold_italic: 'vendor/assets/Open_Sans/OpenSans-BoldItalic.ttf'
43
+ })
44
+ font_families.update('Monospace' => {
45
+ normal: 'vendor/assets/Overpass_Mono/OverpassMono-Regular.ttf',
46
+ bold: 'vendor/assets/Overpass_Mono/OverpassMono-Bold.ttf'
47
+ })
48
+ font 'OpenSans'
49
+ font_size @base_table_font_size
50
+ end
51
+
52
+ def format_text(text_in)
53
+ {
54
+ content: text_in,
55
+ kerning: true,
56
+ inline_format: true
57
+ }
58
+ end
59
+
60
+ def page_footer
61
+ bounding_box([0, @footer_height],
62
+ width: @printable_width,
63
+ height: @footer_height) do
64
+ table(footer_data, width: @printable_width) do |t|
65
+ t.column(0).align = :left
66
+ t.column(1).align = :center
67
+ t.column(2).align = :right
68
+ t.cells.borders = []
69
+ t.cells.padding = 0
70
+ end
71
+ end
72
+ end
73
+
74
+ def footer_data
75
+ footer_data_array = [[
76
+ format_text("<font size=9>#{Date.today.strftime('%-d %B %Y')}</font>"),
77
+ format_text("<b>#{'i' * (page_number - 1)}</b>"),
78
+ format_text("<font size=9><b>Customs Tariff</b> Vol 2</font>")
79
+ ]]
80
+ footer_data_array
81
+ end
82
+
83
+ def build
84
+ cover
85
+
86
+ start_new_page
87
+
88
+ layout
89
+ end
90
+
91
+ def cover
92
+ opts = {
93
+ kerning: true,
94
+ inline_format: true,
95
+ size: @base_table_font_size
96
+ }
97
+ image "vendor/assets/HMRC-logo.png", width: 180
98
+ text_box "<font size='20'><b>Volume 2</b></font>\n<font size='17'>Schedule of duty and trade\nstatistical descriptions,\ncodes and rates</font>", at: [(@printable_width / 3), @printable_height - 100], inline_format: true
99
+ text_box "<font size='32'>Integrated\nTariff of the\nUnited Kingdom</font>\n\n\n<font size='12'>Short title: <i>TARIFF</i>\n\n\nwww.gov.uk/trade-tariff\n\n\n<b>#{Date.today.strftime('%-d %B %Y')}</b>\n\n\n\n\n\n\n\n</font>", at: [(@printable_width / 3) * 2 + (@base_table_font_size * 3), @printable_height - 100], inline_format: true
100
+ stroke_rectangle [0, @printable_height - 200], ((@printable_width / 3) * 2), 190
101
+ text_box "<font size='11'><b><u>Notice to all Users</u></b></font>", at: [20, @printable_height - 210], inline_format: true, width: ((@printable_width / 3) * 2) - 40, align: :center
102
+ text_box "<font size='11'><b>#{notice_content}</b></font>", at: [20, @printable_height - 228], inline_format: true, width: ((@printable_width / 3) * 2) - 40
103
+ end
104
+
105
+ def notice_content
106
+ <<~NOTICE
107
+ Users should be aware that in any case where information in the UK Tariff or Customs Handling of Import and Export Freight (CHIEF) system is at variance with that contianed in the appropirate Community legislation published in the Official Journal of the European Communities, the latter will represent the correct legal position.
108
+ Whilst every effort is made to ensre the accuracy of the UK Tariff, the onus remains with the User to consult the Official Journal as necessary and to ensure that the correct duties are paid at importation. In instances where the Customs Authorities are at error, the User may still be liable for any additional duty that may be demanded as a result of that error being discovered.
109
+ The Official Journal is accessible on the Commission's Europa website:
110
+ https://eur-lex.europa.eu/oj/direct-access.html
111
+ NOTICE
112
+ end
113
+
114
+ def layout
115
+ opts = {
116
+ kerning: true,
117
+ inline_format: true,
118
+ size: @base_table_font_size
119
+ }
120
+ column_box([0, cursor], columns: 3, width: bounds.width, height: (@printable_height - @footer_height - (@printable_height - cursor) + 20), spacer: (@base_table_font_size * 3)) do
121
+ text(layout_content, opts)
122
+ end
123
+ end
124
+
125
+ def layout_content
126
+ <<~CONTENT
127
+ <font size="13"><b>VOLUME 2 Part 1</b></font>
128
+ <font size="17"><b>Guide to the Schedule</b></font>
129
+
130
+ <font size="13"><b>Section 1: Introduction</b></font>
131
+
132
+ <b>1.1 - The Integrated Tariff</b>
133
+
134
+ Both the UK Tariff and the Combined Nomenclature of the EC are based on the based on the internationally agreed system of classification known as the Harmonized Commodity Description and Coding System of the Customs Co-operation Council. This nomenclature provides a systematic classification of all goods in international trade, designed to ensure, with the aid of the General Rules for the interpretation of the Nomenclature (see below) and Notes to the Sections, Chapters and Subheadings, that any product or article falls to be classified in one place and one place only.
135
+
136
+ <b>1.2 The schedule of the Integrated Tariff ('the Schedule')</b>
137
+
138
+ A guide to the general system of classification is provided by the Section and Chapter titles which are set out separtately immediately before the Schedule. The Schedule combines:
139
+
140
+ 1.2.1 - The Harmonized Commodity Description and Coding System of the Customs Co-operation Council (short title: the Harmonized System and referred to as the HS).
141
+
142
+ 1.2.2 - The Combined Nomenclature of the European Community.
143
+
144
+ 1.2.3 - other tariff related mneasures of the European Community, including preferences, quotas, suspensions, and measures connected with the common agricultural policy integrated into the schedule (short title: TARIC). A list of measures included in TARIC will be found in Section 5.
145
+
146
+ 1.2.4 - UK excise duty requirements, except hydrocarbon oil duty descriptions generally (see Section 2).
147
+
148
+
149
+ <font size="13"><b>Section 2: Layout of the Schedule</b></font>
150
+
151
+ <b>2.1 - Column 1 - Heading numbers and descriptions</b>
152
+
153
+ 2.1.1 - The Column contains:
154
+ - heading numbers (4 digits) and descriptions which derive from the main headings of the Harmonized System. These are printed in <b>BOLD CAPITALS</b> and indicate the scope of headings;
155
+ - subheadings which also derive from the Harmonized System. These are printed in <b>bold lowercase</b> type;
156
+ - subheadings included for Combined Nomenclature printed in medium type;
157
+ - other subheadings printed in <i>light italicised</i> type, describing particular goods subject to tariff measures (TARIC).
158
+
159
+ 2.1.2 - Specimens of the various forms and presentations of integrated headings and subheadings, are shown in the layout above and are described in the following sub-paragraph.
160
+
161
+ 2.1.3 - In the specimen layout above:
162
+
163
+ '48.09 CARBON PAPER ... OR SHEETS' is an HS heading that is further subdivided into HS subheadings, some of which are further subdivided into Community subheadings.
164
+
165
+ 'Tarred, bituminized or asphalted paper and paerboard' is an HS subheading for which no further breakdown exists for Community purposes.
166
+
167
+ 'Carbon or similar copying papers' is a Combined Nomenclature sub-division.
168
+
169
+ 2.1.4 - Headings and subheadings followed by the term '(EURATOM)' are goods covered by the European Atomic Energy Commission Treaty. The presence of this term does not affect the scope of any heading or sub-heading.
170
+
171
+ 2.1.5 - Where the reference '(TEXT and 3 digits)' appears after a description in this column, it indicates the textile category that applies.
172
+
173
+ <b>2.2 - Column 2 - Commodity Codes</b>
174
+
175
+ 2.2.1 - In addition to the heading numbers and descriptions which appear under column 1, provision is made under column 2 for the classification of goods to be indicated by a commodity code number unique to each heading or subheading. Subject to the exceptions set out below, in the case of goods moving within the Community (intra-EC goods) and all exports, only the code number which appears under column 2A should be used. Imports from non-EC countries should be classified in accordance with the code number which combines columns 2A and 2B.
176
+
177
+ 2.2.2 - <b>Column 2A - 8 digits.</b> The first four digits are those of the Harmonized System (HS) headings and the fifth and sixth represent HS subheadings. EC Combined Nomenclature requirements are met by the seventh and eighth digits. For intra-EC movement of goods not in free circulation, for whch a C88SAD entry is completd and for exports to non-EC countries only the 8-digit code should be used.
178
+
179
+ 2.2.3 - <b>Column 2B - 2 digits.</b> this colum provides for two additional digits to cover EC-related tariff and related measures which, in general, apply only to importations from non-EC countries and which have been included in the integrated tariff of the Community. Where no further breakdown of the Combined Nomenclature is required to accomodate tariff measures (most preferences, for example) the two digits are 00 and are shown on the same line as the 8-digit code. Subheadings established for TARIC purposes are shown in light italicised type and are notable for the fact that only the two digits of column 2 appear against the descriptions. They are included after the breakdown of headings at 8-digit level to avoid repetition and to spare the tariff user concerned only with intra-Community trade and exports from having to consider TARIC descriptions which apply in the main only to imports from outside the Community.
180
+
181
+ <b>The declaration of a combined 10-digit code is mandatory for importations from outside the Community even where the 2 two characters are both zero.</b>
182
+
183
+ 2.2.4 <b>Additional code. (general). Imports from outside the Community that are subject to anti-dumping duties or subject to agricultural component (in most cases) will also require an additional code of 4 digits to be declared in conjunction with the 10-digit code. In such instacnes where the additional code is required it is to be declared in conjunction with the 8-digit code. A footnote reference appears in Column 3 of the Schedule against TARIC lines which require the additional code to be used.</b>
184
+
185
+ 2.2.5 - <b>Examples.</b> The following 2 examples, based on the specimen included at paragraph 2.1.2 above, illustrate how the level 2 code operates in practice:
186
+
187
+ Example 1: The 8-digit code 481200 00 would be appropriate for goods falling within heading 4812 and coming from a Community source while the 10-digit code 481200 00 00 would be required for the same goods imported from a non-community source.
188
+
189
+ Example 2: The goods described at lines 11-20 imported from an EC source would have to be coded only at the 8-digit level 481121 00 while similar goods from a non-Community source would require the full 10-digit code 481121 00 10.
190
+
191
+ <b>It is important to remember that the last two digits should be selected only after the 8-digit code has been determined.</b>
192
+
193
+ <b>2.3 - Column 3 - Specific Provisions</b>
194
+
195
+ This column indcludes a variety of information for a wide range of purposes. The detail is frequently in abbreviated form. A key to symbols and abbreviations will be found at the end of this Part, and Section 5 contains a fuller explanation of the tariff measures integrated in the Schedule. Information that is too detailed to be included in the column will appear as a footnote, or at the end of the relevant Chapter.
196
+
197
+ <b>2.4 - Column 4 - Unit of Quantity</b>
198
+
199
+ The satandard quantity is the kilogram. For some subheadings however a second quantity declaration is required, normally when duties (customs or excise) are calculated on a specific basis. Occasionally a third quantity must be declared.
200
+
201
+ <b>2.5 - Column 5 - Full rate of duty</b>
202
+
203
+ The rate of duty shown is the rate applicable under the Common Customs Tariff. The duties expressed as percentage rates are to be calculated on the value of the goods as defined in Volume 1 Part 14. In addition, some duties are expressed in European currency the Euro (see paragraph 4.2).
204
+
205
+ <b>2.6 - Column 6 - Preferential rates of duty</b>
206
+
207
+ Detail of beneficiary countries and county groups is set out in abbreviated form. A key to most of the countries is included on divider cards supplied with the Tariff. A full listing of constituent members of country groups will be found in either Section 6 or Volume 1 Part 7. The duties expressed as percentage rates are to be calculated on the value of the goods as defined in Volume 1 Part 14.
208
+
209
+ <b>Note</b>
210
+ <b>In the case of all preferential agreements, where no reduced rate of duty is shown the full rate of duty applies.</b>
211
+
212
+ <b>2.7 - Column 7 - VAT rate</b>
213
+
214
+ An indication of liability to VAT is provided here (see Volume 1 Part 13). Where goods described in Column 2 may be subject to alternative rates of tax according to elements of description not included specifically in the text for customs duty purposes, all possible VAT rates are shown in column 7. The applicable rate must be determined by reference to VAT leaflets.
215
+
216
+ <b>2.8 - Footnotes and end of chapter information</b>
217
+
218
+ Where it is not practicable to include information and requirements against the line of the Tariff these are shown as footnotes on the same page or are set out at the end of the Chapter in which they apply under the Commodity Code reference. This additional material has the same legal force as all other information in the Schedule.
219
+
220
+ <b>2.9 - Validity of Tariff information</b>
221
+
222
+ Every effort is made to include all relevant information and to ensure that changes throught the year are promptly taken account of in the Tariff. The volatile and temporary nature of some tariff measures means that certain changes may occur before detail can be included in the Tariff as an ammendment. Up to date information about tariff changes is available at local customs offices. Alternatively, details are published in the Official Journal of the European Communities.
223
+ CONTENT
224
+ end
225
+ end
@@ -0,0 +1,62 @@
1
+ module Uktt
2
+ # A Chapter object for dealing with an API resource
3
+ class Heading
4
+ attr_accessor :config, :heading_id, :response
5
+
6
+ def initialize(opts = {})
7
+ @heading_id = opts[:heading_id] || nil
8
+ Uktt.configure(opts)
9
+ @config = Uktt.config
10
+ @response = nil
11
+ end
12
+
13
+ def retrieve
14
+ return '@chapter_id cannot be nil' if @heading_id.nil?
15
+
16
+ fetch "#{HEADING}/#{@heading_id}.json"
17
+ end
18
+
19
+ def goods_nomenclatures
20
+ return '@chapter_id cannot be nil' if @heading_id.nil?
21
+
22
+ fetch "#{GOODS_NOMENCLATURE}/heading/#{@heading_id}.json"
23
+ end
24
+
25
+ def note
26
+ 'a heading cannot have a note'
27
+ end
28
+
29
+ def changes
30
+ return '@chapter_id cannot be nil' if @heading_id.nil?
31
+
32
+ fetch "#{HEADING}/#{@heading_id}/changes.json"
33
+ end
34
+
35
+ def config=(new_opts = {})
36
+ merged_opts = Uktt.config.merge(new_opts)
37
+ Uktt.configure merged_opts
38
+ @heading_id = merged_opts[:heading_id] || @heading_id
39
+ @config = Uktt.config
40
+ end
41
+
42
+ def find(id)
43
+ return '@response is nil, run #retrieve first' unless @response
44
+
45
+ response = @response.included.select do |obj|
46
+ obj.id === id || obj.type === id
47
+ end
48
+ response.length == 1 ? response.first : response
49
+ end
50
+
51
+ private
52
+
53
+ def fetch(resource)
54
+ @response = Uktt::Http.new(
55
+ @config[:host],
56
+ @config[:version],
57
+ @config[:debug])
58
+ .retrieve(resource,
59
+ @config[:return_json])
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,43 @@
1
+ require 'faraday'
2
+ require 'json'
3
+
4
+ module Uktt
5
+ # An object for handling network requests
6
+ class Http
7
+ def initialize(host = nil, version = nil, debug = false)
8
+ @host = host || API_HOST_LOCAL
9
+ @version = version || API_VERSION
10
+ @conn = Faraday.new(url: @host) do |faraday|
11
+ faraday.response(:logger) if debug
12
+ faraday.adapter Faraday.default_adapter
13
+ end
14
+ end
15
+
16
+ def retrieve(resource, return_json = false)
17
+ json = @conn.get do |request|
18
+ request.url([@version, resource].join('/'))
19
+ end.body
20
+ return json if return_json
21
+
22
+ JSON.parse(json, object_class: OpenStruct)
23
+ end
24
+
25
+ class << self
26
+ def use_production
27
+ !ENV['PROD'].nil? && ENV['PROD'].casecmp('true').zero?
28
+ end
29
+
30
+ def spec_version
31
+ return @version unless @version.nil?
32
+
33
+ ENV['VER'] ? ENV['VER'].to_s : 'v1'
34
+ end
35
+
36
+ def api_host
37
+ return ENV['HOST'] if ENV['HOST']
38
+
39
+ use_production ? Uktt::API_HOST_PROD : Uktt::API_HOST_LOCAL
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,53 @@
1
+ module Uktt
2
+ # A MonetaryExchangeRate object for dealing with an API resource
3
+ class MonetaryExchangeRate
4
+ attr_accessor :monetary_exchange_rate_id, :config, :response
5
+
6
+ def initialize(opts = {})
7
+ @monetary_exchange_rate_id = opts[:monetary_exchange_rate_id] || nil
8
+ Uktt.configure(opts)
9
+ @config = Uktt.config
10
+ end
11
+
12
+ def retrieve_all
13
+ fetch "#{M_X_RATE}.json"
14
+ end
15
+
16
+ def latest(currency)
17
+ retrieve_all unless @response
18
+
19
+ case @config[:version]
20
+ when 'v1'
21
+ @response.select{ |obj| obj.child_monetary_unit_code == currency.upcase }
22
+ .sort_by(&:validity_start_date)
23
+ .last.exchange_rate.to_f
24
+ when 'v2'
25
+ @response.data.select{ |obj| obj.attributes.child_monetary_unit_code == currency.upcase }
26
+ .sort_by{ |obj| obj.attributes.validity_start_date }
27
+ .last.attributes.exchange_rate.to_f
28
+ else
29
+ raise StandardError.new "`#{@opts[:version]}` is not a supported API version. Supported API versions are: v1 and v2"
30
+ end
31
+ end
32
+
33
+ def config=(new_opts = {})
34
+ merged_opts = Uktt.config.merge(new_opts)
35
+ Uktt.configure merged_opts
36
+ @monetary_exchange_rate_id = merged_opts[:monetary_exchange_rate_id] || @monetary_exchange_rate_id
37
+ @config = Uktt.config
38
+ end
39
+
40
+ private
41
+
42
+ def fetch(resource)
43
+ @response = Uktt::Http.new(
44
+ @config[:host],
45
+ @config[:version],
46
+ @config[:debug]
47
+ ).retrieve(
48
+ resource,
49
+ @config[:return_json]
50
+ )
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,38 @@
1
+ require 'uktt/export_chapter_pdf'
2
+ require 'uktt/export_cover_pdf'
3
+
4
+ module Uktt
5
+ # An object for producing PDF files of individual chapters in the Tariff
6
+ class Pdf
7
+ attr_accessor :chapter_id, :config
8
+
9
+ def initialize(opts = {})
10
+ @chapter_id = opts[:chapter_id] || nil
11
+ @filepath = opts[:filepath] || "#{Dir.pwd}/#{@chapter_id || 'cover'}.pdf"
12
+ @currency = opts[:currency] || Uktt::PARENT_CURRENCY
13
+ Uktt.configure(opts)
14
+ @config = Uktt.config
15
+ end
16
+
17
+ def make_chapter
18
+ pdf = ExportChapterPdf.new(@config.merge(chapter_id: @chapter_id))
19
+ pdf.save_as(@filepath)
20
+ @filepath
21
+ end
22
+
23
+ def config=(new_opts = {})
24
+ merged_opts = Uktt.config.merge(new_opts)
25
+ Uktt.configure merged_opts
26
+ @chapter_id = merged_opts[:chapter_id] || @chapter_id
27
+ @filepath = merged_opts[:filepath] || @filepath
28
+ @currency = merged_opts[:currency] || @currency
29
+ @config = Uktt.config
30
+ end
31
+
32
+ def make_cover
33
+ pdf = ExportCoverPdf.new
34
+ pdf.save_as(@filepath)
35
+ @filepath
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,31 @@
1
+ module Uktt
2
+ # A Quota object for dealing with an API resource
3
+ class Quota
4
+ attr_accessor :config
5
+
6
+ def initialize(opts = {})
7
+ Uktt.configure(opts)
8
+ @config = Uktt.config
9
+ end
10
+
11
+ def search(params)
12
+ fetch "#{QUOTA}/search.json?#{URI.encode_www_form(params)}"
13
+ end
14
+
15
+ def config=(new_opts = {})
16
+ merged_opts = Uktt.config.merge(new_opts)
17
+ Uktt.configure merged_opts
18
+ @config = Uktt.config
19
+ end
20
+
21
+ private
22
+
23
+ def fetch(resource)
24
+ Uktt::Http.new(@config[:host],
25
+ @config[:version],
26
+ @config[:debug])
27
+ .retrieve(resource,
28
+ @config[:return_json])
29
+ end
30
+ end
31
+ end