kamome 0.1.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.
@@ -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