kamome 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Kamome
4
+ class Configuration
5
+ require 'securerandom'
6
+ require 'tmpdir'
7
+
8
+ attr_accessor :tmp_path
9
+ attr_accessor :open_uri_options
10
+
11
+ def initialize
12
+ @tmp_path = ::File.join(Dir.tmpdir, 'kamome', SecureRandom.hex(8))
13
+ @open_uri_options = {}
14
+ end
15
+
16
+ def working_directory
17
+ @working_directory ||= ::Pathname.new(@tmp_path.to_s)
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'kamome/transformations/general_csv'
4
+ require 'kamome/transformations/jigyosho_csv'
5
+ require 'csv'
6
+
7
+ module Kamome
8
+ class CsvHandler
9
+ def initialize(operation)
10
+ @operation = operation
11
+ end
12
+
13
+ def call(csv_path)
14
+ ::CSV.foreach(csv_path) do |row|
15
+ obj = transform(row)
16
+ yield(obj, $INPUT_LINE_NUMBER)
17
+ end
18
+ end
19
+
20
+ private
21
+
22
+ def transform(row)
23
+ transformer.public_send(transformed_method, row)
24
+ end
25
+
26
+ def transformed_method
27
+ return :generate_hash if @operation.type_hash?
28
+ return :generate_detail_model if @operation.type_detail?
29
+
30
+ :generate_model
31
+ end
32
+
33
+ def transformer
34
+ @transformer ||= @operation.genre_jigyosho? ? jigyosho_transformer : general_transformer
35
+ end
36
+
37
+ def jigyosho_transformer
38
+ ::Kamome::Transformations::JigyoshoCsv.new
39
+ end
40
+
41
+ def general_transformer
42
+ ::Kamome::Transformations::GeneralCsv.new
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,56 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Kamome
4
+ class Downloader
5
+ require 'open-uri'
6
+ require 'securerandom'
7
+ require 'fileutils'
8
+ require 'zip'
9
+ require 'nkf'
10
+
11
+ def initialize(config)
12
+ @config = config
13
+ end
14
+
15
+ # @return [Pathname] CSV file path
16
+ def run(url:)
17
+ zip_path = download(url)
18
+ csv_path = unpack(zip_path)
19
+ zip_path.delete
20
+ csv_path
21
+ rescue StandardError => e
22
+ raise Kamome::DownloadError, "#{e.class}: #{e.message}"
23
+ end
24
+
25
+ private
26
+
27
+ # @return [Pathname] downloaded file
28
+ def download(url)
29
+ dest = @config.working_directory.join(SecureRandom.hex(8) + '.zip')
30
+ ::FileUtils.mkdir_p(dest.dirname)
31
+
32
+ ::OpenURI.open_uri(url, @config.open_uri_options) do |response|
33
+ ::File.binwrite(dest, response.read)
34
+ end
35
+ dest
36
+ end
37
+
38
+ def unpack(src)
39
+ # convert encoding Shift_JIS to UTF-8 (and half width Katakana to full width Katakana)
40
+ content = ::NKF.nkf('-w -Lu', take_csv_entry(src).get_input_stream.read)
41
+
42
+ dest = src.sub('.zip', '.csv')
43
+ ::File.binwrite(dest, content)
44
+ dest
45
+ end
46
+
47
+ def take_csv_entry(src)
48
+ entry = ::Zip::File.open(src) do |zipfile|
49
+ zipfile.select { |o| o.name =~ /.*\.csv/i }.first
50
+ end
51
+ raise ::Kamome::DownloadError, 'Not found csvfile in zipfile' if entry.nil?
52
+
53
+ entry
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'kamome/downloader'
4
+ require 'kamome/csv_handler'
5
+
6
+ module Kamome
7
+ class Loader
8
+ def initialize(config:)
9
+ @config = config
10
+ end
11
+
12
+ def call(operation:, &block)
13
+ csv_handler = build_csv_handler(operation)
14
+
15
+ operation.urls.each do |url|
16
+ csv_path = download(url)
17
+ csv_handler.call(csv_path, &block)
18
+ csv_path.delete
19
+ end
20
+ end
21
+
22
+ private
23
+
24
+ def download(url)
25
+ downloader.run(url: url)
26
+ end
27
+
28
+ def downloader
29
+ @downloader ||= ::Kamome::Downloader.new(@config)
30
+ end
31
+
32
+ def build_csv_handler(operation)
33
+ ::Kamome::CsvHandler.new(operation)
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,83 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Kamome
4
+ module Models
5
+ class Address
6
+ # @!attribute [rw] code
7
+ # 全国地方公共団体コード
8
+ # @return [String]
9
+ attr_accessor :code
10
+
11
+ # @!attribute [rw] zipcode
12
+ # 郵便番号(7桁)
13
+ # @return [String]
14
+ attr_accessor :zipcode
15
+
16
+ # @!attribute [rw] prefecture
17
+ # 都道府県名
18
+ # @return [String]
19
+ attr_accessor :prefecture
20
+
21
+ # @!attribute [rw] city
22
+ # 市区町村
23
+ # @return [String]
24
+ attr_accessor :city
25
+
26
+ # @!attribute [rw] town
27
+ # 町域
28
+ # @return [String]
29
+ attr_accessor :town
30
+
31
+ # @!attribute [rw] street
32
+ # 番地, 建物等
33
+ # @return [String]
34
+ attr_accessor :street
35
+
36
+ # @!attribute [rw] company_name
37
+ # 企業名/団体名 等
38
+ # @return [String]
39
+ attr_accessor :company_name
40
+
41
+ # @!attribute [rw] post_office_box
42
+ # 私書箱名
43
+ # @return [String]
44
+ attr_accessor :post_office_box
45
+
46
+ # @!attribute [rw] state
47
+ # 状態
48
+ # 0: 変更なし
49
+ # 1: 変更あり
50
+ # 2: 削除
51
+ # @return [Integer]
52
+ attr_accessor :state
53
+
54
+ def initialize(params = {})
55
+ params.each do |key, value|
56
+ public_send("#{key}=", value)
57
+ end
58
+ end
59
+
60
+ def attributes
61
+ {
62
+ code: code,
63
+ zipcode: zipcode,
64
+ prefecture: prefecture,
65
+ city: city,
66
+ town: town,
67
+ street: street,
68
+ company_name: company_name,
69
+ post_office_box: post_office_box,
70
+ state: state
71
+ }
72
+ end
73
+
74
+ def changed?
75
+ state == 1
76
+ end
77
+
78
+ def delete?
79
+ state == 2
80
+ end
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,107 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Kamome
4
+ module Models
5
+ # CSV Model: 読み仮名データの促音・拗音を小書きで表記するもの
6
+ # @see https://www.post.japanpost.jp/zipcode/dl/readme.html
7
+ class General
8
+ # @!attribute [rw] code
9
+ # 全国地方公共団体コード(JIS X0401, X0402), 半角数値
10
+ # @return [String]
11
+ attr_accessor :code
12
+
13
+ # @!attribute [rw] zipcode
14
+ # 郵便番号, 半角数値7桁
15
+ # @return [String]
16
+ attr_accessor :zipcode
17
+
18
+ # @!attribute [rw] prefecture_kana
19
+ # 都道府県名 カナ
20
+ # @return [String]
21
+ attr_accessor :prefecture_kana
22
+
23
+ # @!attribute [rw] city_kana
24
+ # 市区町村名 カナ
25
+ # @return [String]
26
+ attr_accessor :city_kana
27
+
28
+ # @!attribute [rw] town_kana
29
+ # 町域名 カナ
30
+ # @return [String]
31
+ attr_accessor :town_kana
32
+
33
+ # @!attribute [rw] prefecture
34
+ # 都道府県名 漢字
35
+ # @return [String]
36
+ attr_accessor :prefecture
37
+
38
+ # @!attribute [rw] city
39
+ # 市区町村名 漢字
40
+ # @return [String]
41
+ attr_accessor :city
42
+
43
+ # @!attribute [rw] town
44
+ # 町域名 漢字
45
+ # @return [String]
46
+ attr_accessor :town
47
+
48
+ # @!attribute [rw] ambiguous_town
49
+ # 一町域が二以上の郵便番号で表される場合 true
50
+ # @return [Boolean]
51
+ attr_accessor :ambiguous_town
52
+
53
+ # @!attribute [rw] ambiguous_street
54
+ # 小字毎に番地が起番されている町域の場合 true
55
+ # @return [Boolean]
56
+ attr_accessor :ambiguous_street
57
+
58
+ # @!attribute [rw] required_chome
59
+ # 丁目を有する町域の場合 true
60
+ # @return [Boolean]
61
+ attr_accessor :required_chome
62
+
63
+ # @!attribute [rw] ambiguous_zipcode
64
+ # 一つの郵便番号で二以上の町域を表す場合 true
65
+ # @return [Boolean]
66
+ attr_accessor :ambiguous_zipcode
67
+
68
+ # @!attribute [rw] state
69
+ # 更新の表示
70
+ # 0: 変更なし, 1: 変更あり, 2: 廃止
71
+ # @return [Integer]
72
+ attr_accessor :state
73
+
74
+ # @!attribute [rw] reason
75
+ # 変更理由
76
+ # 0: 変更なし, 1: 市政・区政・町政・分区・政令指定都市施行, 2: 住居表示の実施,
77
+ # 3: 区画整理, 4: 郵便区調整等, 5: 訂正, 6: 廃止
78
+ # @return [Integer]
79
+ attr_accessor :reason
80
+
81
+ def initialize(params = {})
82
+ params.each do |key, value|
83
+ public_send("#{key}=", value)
84
+ end
85
+ end
86
+
87
+ def attributes
88
+ {
89
+ code: code,
90
+ zipcode: zipcode,
91
+ prefecture_kana: prefecture_kana,
92
+ city_kana: city_kana,
93
+ town_kana: town_kana,
94
+ prefecture: prefecture,
95
+ city: city,
96
+ town: town,
97
+ ambiguous_town: ambiguous_town,
98
+ ambiguous_street: ambiguous_street,
99
+ required_chome: required_chome,
100
+ ambiguous_zipcode: ambiguous_zipcode,
101
+ state: state,
102
+ reason: reason
103
+ }
104
+ end
105
+ end
106
+ end
107
+ end
@@ -0,0 +1,106 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Kamome
4
+ module Models
5
+ # CSV Model: 大口事業所個別番号データ
6
+ # @see https://www.post.japanpost.jp/zipcode/dl/jigyosyo/index-zip.html
7
+ # @see https://www.post.japanpost.jp/zipcode/dl/jigyosyo/readme.html
8
+ class Jigyosho
9
+ # @!attribute [rw] code
10
+ # 大口事業所の所在地のJISコード
11
+ # @return [String]
12
+ attr_accessor :code
13
+
14
+ # @!attribute [rw] name_kana
15
+ # 大口事業所名(カナ)
16
+ # @return [String]
17
+ attr_accessor :company_name_kana
18
+
19
+ # @!attribute [rw] name
20
+ # 大口事業所名(漢字)
21
+ # @return [String]
22
+ attr_accessor :company_name
23
+
24
+ # @!attribute [rw] prefecture
25
+ # 都道府県名(漢字)
26
+ # @return [String]
27
+ attr_accessor :prefecture
28
+
29
+ # @!attribute [rw] city
30
+ # 市区町村名(漢字)
31
+ # @return [String]
32
+ attr_accessor :city
33
+
34
+ # @!attribute [rw] town
35
+ # 町域名(漢字)
36
+ # @return [String]
37
+ attr_accessor :town
38
+
39
+ # @!attribute [rw] street
40
+ # 小字名、丁目、番地等(漢字)
41
+ # @return [String]
42
+ attr_accessor :street
43
+
44
+ # @!attribute [rw] post_office_box
45
+ # 私書箱名
46
+ # @return [String]
47
+ attr_accessor :post_office_box
48
+
49
+ # @!attribute [rw] town
50
+ # 大口事業所個別番号
51
+ # @return [String]
52
+ attr_accessor :zipcode
53
+
54
+ # @!attribute [rw] japanpost_office_name
55
+ # 取扱局
56
+ # @return [String]
57
+ attr_accessor :japanpost_office_name
58
+
59
+ # @!attribute [rw] post_office_box
60
+ # 私書箱: true, 大口事業所: false
61
+ # @return [Boolean]
62
+ attr_accessor :has_post_office_box
63
+
64
+ # @!attribute [rw] required_chome
65
+ # 複数番号の有無
66
+ # * 「0」複数番号無し
67
+ # * 「1」複数番号を設定している場合の個別番号の1
68
+ # * 「2」複数番号を設定している場合の個別番号の2
69
+ # * 「3」複数番号を設定している場合の個別番号の3
70
+ # @return [Integer]
71
+ attr_accessor :multiple
72
+
73
+ # @!attribute [rw] state
74
+ # 修正コード
75
+ # * 「0」修正なし
76
+ # * 「1」新規追加
77
+ # * 「5」廃止
78
+ # @return [Integer]
79
+ attr_accessor :state
80
+
81
+ def initialize(params = {})
82
+ params.each do |key, value|
83
+ public_send("#{key}=", value)
84
+ end
85
+ end
86
+
87
+ def attributes
88
+ {
89
+ code: code,
90
+ company_name_kana: company_name_kana,
91
+ company_name: company_name,
92
+ prefecture: prefecture,
93
+ city: city,
94
+ town: town,
95
+ street: street,
96
+ post_office_box: post_office_box,
97
+ zipcode: zipcode,
98
+ japanpost_office_name: japanpost_office_name,
99
+ has_post_office_box: has_post_office_box,
100
+ multiple: multiple,
101
+ state: state
102
+ }
103
+ end
104
+ end
105
+ end
106
+ end