japan_shipping_csv 0.2.2
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/.travis.yml +7 -0
- data/CHANGELOG.md +0 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +6 -0
- data/Gemfile.lock +22 -0
- data/README.md +39 -0
- data/Rakefile +10 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/japan_shipping_csv.gemspec +40 -0
- data/lib/japan_shipping_csv.rb +3 -0
- data/lib/japan_shipping_csv/ehiden.rb +220 -0
- data/lib/japan_shipping_csv/encoding.rb +162 -0
- data/lib/japan_shipping_csv/version.rb +3 -0
- metadata +102 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 66ce156620a2ec645fbe902b2f3b4ff3a8974001bd75ec3696b3032f7358b3e5
|
4
|
+
data.tar.gz: 76c6d23380f8fe1a7686b6d78d9855ff58211a83a1f56f6dd9e6d07bf1281f61
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 5949bb6efe276ca240a70c3e53f01e0f7b8f05368032a4dcdfe1ac67ae0a0da650f9cdae62606da9c3706d9e40a36dbac6f31de07e8b227d951a3957a8055467
|
7
|
+
data.tar.gz: 358964b07ab3741ddb52a5964e0579d409a4db03f33dbb517941e6980ea198be3a5a47509d58bf53bf460b4787ed5dab0f6c034059e39830b5a57f8236dca4ae
|
data/.gitignore
ADDED
data/.travis.yml
ADDED
data/CHANGELOG.md
ADDED
File without changes
|
data/CODE_OF_CONDUCT.md
ADDED
@@ -0,0 +1,74 @@
|
|
1
|
+
# Contributor Covenant Code of Conduct
|
2
|
+
|
3
|
+
## Our Pledge
|
4
|
+
|
5
|
+
In the interest of fostering an open and welcoming environment, we as
|
6
|
+
contributors and maintainers pledge to making participation in our project and
|
7
|
+
our community a harassment-free experience for everyone, regardless of age, body
|
8
|
+
size, disability, ethnicity, gender identity and expression, level of experience,
|
9
|
+
nationality, personal appearance, race, religion, or sexual identity and
|
10
|
+
orientation.
|
11
|
+
|
12
|
+
## Our Standards
|
13
|
+
|
14
|
+
Examples of behavior that contributes to creating a positive environment
|
15
|
+
include:
|
16
|
+
|
17
|
+
* Using welcoming and inclusive language
|
18
|
+
* Being respectful of differing viewpoints and experiences
|
19
|
+
* Gracefully accepting constructive criticism
|
20
|
+
* Focusing on what is best for the community
|
21
|
+
* Showing empathy towards other community members
|
22
|
+
|
23
|
+
Examples of unacceptable behavior by participants include:
|
24
|
+
|
25
|
+
* The use of sexualized language or imagery and unwelcome sexual attention or
|
26
|
+
advances
|
27
|
+
* Trolling, insulting/derogatory comments, and personal or political attacks
|
28
|
+
* Public or private harassment
|
29
|
+
* Publishing others' private information, such as a physical or electronic
|
30
|
+
address, without explicit permission
|
31
|
+
* Other conduct which could reasonably be considered inappropriate in a
|
32
|
+
professional setting
|
33
|
+
|
34
|
+
## Our Responsibilities
|
35
|
+
|
36
|
+
Project maintainers are responsible for clarifying the standards of acceptable
|
37
|
+
behavior and are expected to take appropriate and fair corrective action in
|
38
|
+
response to any instances of unacceptable behavior.
|
39
|
+
|
40
|
+
Project maintainers have the right and responsibility to remove, edit, or
|
41
|
+
reject comments, commits, code, wiki edits, issues, and other contributions
|
42
|
+
that are not aligned to this Code of Conduct, or to ban temporarily or
|
43
|
+
permanently any contributor for other behaviors that they deem inappropriate,
|
44
|
+
threatening, offensive, or harmful.
|
45
|
+
|
46
|
+
## Scope
|
47
|
+
|
48
|
+
This Code of Conduct applies both within project spaces and in public spaces
|
49
|
+
when an individual is representing the project or its community. Examples of
|
50
|
+
representing a project or community include using an official project e-mail
|
51
|
+
address, posting via an official social media account, or acting as an appointed
|
52
|
+
representative at an online or offline event. Representation of a project may be
|
53
|
+
further defined and clarified by project maintainers.
|
54
|
+
|
55
|
+
## Enforcement
|
56
|
+
|
57
|
+
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
58
|
+
reported by contacting the project team at storkyd@gmail.com. All
|
59
|
+
complaints will be reviewed and investigated and will result in a response that
|
60
|
+
is deemed necessary and appropriate to the circumstances. The project team is
|
61
|
+
obligated to maintain confidentiality with regard to the reporter of an incident.
|
62
|
+
Further details of specific enforcement policies may be posted separately.
|
63
|
+
|
64
|
+
Project maintainers who do not follow or enforce the Code of Conduct in good
|
65
|
+
faith may face temporary or permanent repercussions as determined by other
|
66
|
+
members of the project's leadership.
|
67
|
+
|
68
|
+
## Attribution
|
69
|
+
|
70
|
+
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
|
71
|
+
available at [http://contributor-covenant.org/version/1/4][version]
|
72
|
+
|
73
|
+
[homepage]: http://contributor-covenant.org
|
74
|
+
[version]: http://contributor-covenant.org/version/1/4/
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
japan_shipping_csv (0.2.2)
|
5
|
+
|
6
|
+
GEM
|
7
|
+
remote: https://rubygems.org/
|
8
|
+
specs:
|
9
|
+
minitest (5.14.1)
|
10
|
+
rake (10.5.0)
|
11
|
+
|
12
|
+
PLATFORMS
|
13
|
+
ruby
|
14
|
+
|
15
|
+
DEPENDENCIES
|
16
|
+
bundler (~> 1.16)
|
17
|
+
japan_shipping_csv!
|
18
|
+
minitest (~> 5.0)
|
19
|
+
rake (~> 10.0)
|
20
|
+
|
21
|
+
BUNDLED WITH
|
22
|
+
1.16.6
|
data/README.md
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
# JapanShippingCsv
|
2
|
+
|
3
|
+
Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/japan_shipping_csv`. To experiment with that code, run `bin/console` for an interactive prompt.
|
4
|
+
|
5
|
+
TODO: Delete this and the text above, and describe your gem
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
|
9
|
+
Add this line to your application's Gemfile:
|
10
|
+
|
11
|
+
```ruby
|
12
|
+
gem 'japan_shipping_csv'
|
13
|
+
```
|
14
|
+
|
15
|
+
And then execute:
|
16
|
+
|
17
|
+
$ bundle
|
18
|
+
|
19
|
+
Or install it yourself as:
|
20
|
+
|
21
|
+
$ gem install japan_shipping_csv
|
22
|
+
|
23
|
+
## Usage
|
24
|
+
|
25
|
+
TODO: Write usage instructions here
|
26
|
+
|
27
|
+
## Development
|
28
|
+
|
29
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
30
|
+
|
31
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
32
|
+
|
33
|
+
## Contributing
|
34
|
+
|
35
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/japan_shipping_csv. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
|
36
|
+
|
37
|
+
## Code of Conduct
|
38
|
+
|
39
|
+
Everyone interacting in the JapanShippingCsv project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/[USERNAME]/japan_shipping_csv/blob/master/CODE_OF_CONDUCT.md).
|
data/Rakefile
ADDED
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "japan_shipping_csv"
|
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(__FILE__)
|
data/bin/setup
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
lib = File.expand_path("../lib", __FILE__)
|
2
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
3
|
+
require "japan_shipping_csv/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |spec|
|
6
|
+
spec.name = "japan_shipping_csv"
|
7
|
+
spec.version = JapanShippingCSV::VERSION
|
8
|
+
spec.authors = ["Shaun Cechner"]
|
9
|
+
spec.email = ["shaun@brewkeeper.com.au"]
|
10
|
+
|
11
|
+
spec.summary = %q{Export orders to Japan Shipping Carrier compatible CSV.}
|
12
|
+
# spec.description = %q{TODO: Write a longer description or delete this line.}
|
13
|
+
spec.homepage = "https://gitlab.com/brewkeeper/japan-shipping-csv"
|
14
|
+
|
15
|
+
# Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
|
16
|
+
# to allow pushing to a single host or delete this section to allow pushing to any host.
|
17
|
+
if spec.respond_to?(:metadata)
|
18
|
+
# spec.metadata["allowed_push_host"] = "TODO: Set to 'http://mygemserver.com'"
|
19
|
+
|
20
|
+
spec.metadata["homepage_uri"] = spec.homepage
|
21
|
+
# spec.metadata["source_code_uri"] = "TODO: Put your gem's public repo URL here."
|
22
|
+
spec.metadata["changelog_uri"] = "https://gitlab.com/brewkeeper/japan-shipping-csv/-/blob/master/CHANGELOG.md"
|
23
|
+
else
|
24
|
+
raise "RubyGems 2.0 or newer is required to protect against " \
|
25
|
+
"public gem pushes."
|
26
|
+
end
|
27
|
+
|
28
|
+
# Specify which files should be added to the gem when it is released.
|
29
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
30
|
+
spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
|
31
|
+
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
32
|
+
end
|
33
|
+
spec.bindir = "exe"
|
34
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
35
|
+
spec.require_paths = ["lib"]
|
36
|
+
|
37
|
+
spec.add_development_dependency "bundler", "~> 1.16"
|
38
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
39
|
+
spec.add_development_dependency "minitest", "~> 5.0"
|
40
|
+
end
|
@@ -0,0 +1,220 @@
|
|
1
|
+
require 'csv'
|
2
|
+
|
3
|
+
module JapanShippingCSV
|
4
|
+
module Ehiden
|
5
|
+
FieldSpec = Struct.new(:header, :description, :is_required, :max_length, :valid_encodings, :valid_values, :default_value) do
|
6
|
+
def encoding_errors(value)
|
7
|
+
if !is_required && (value.nil? || value.empty?)
|
8
|
+
return []
|
9
|
+
end
|
10
|
+
if is_required && (value.nil? || value.empty?)
|
11
|
+
return ["value is required"]
|
12
|
+
end
|
13
|
+
|
14
|
+
results = []
|
15
|
+
|
16
|
+
if !valid_values.nil? && !valid_values.include?(value)
|
17
|
+
results << "must be one of #{valid_values.join(", ")}"
|
18
|
+
end
|
19
|
+
if value.length > max_length
|
20
|
+
results << "is longer than #{max_length} characters"
|
21
|
+
end
|
22
|
+
if valid_encodings
|
23
|
+
# TODO
|
24
|
+
# go through each character in the value, and veriy that it matches the valid encodings
|
25
|
+
if !Encoding::is_valid_string(value, valid_encodings)
|
26
|
+
results << "contains invalid character"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
results
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
class Field
|
34
|
+
attr_reader :spec, :value
|
35
|
+
|
36
|
+
def initialize(spec, value)
|
37
|
+
@spec = spec
|
38
|
+
@value = value || @spec.default_value
|
39
|
+
@value = Encoding::reencode(@value, @spec.valid_encodings)
|
40
|
+
end
|
41
|
+
|
42
|
+
def encoding_errors
|
43
|
+
@spec.encoding_errors(@value)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
class CSV
|
48
|
+
def initialize(options = {})
|
49
|
+
package_codes = ["001", "002", "003", "004", "005", "006", "007", "008"]
|
50
|
+
# auto packageCodes = QStringList()
|
51
|
+
# << QString("|")
|
52
|
+
# << QString("001|%1").arg(tr("Boxed Goods"))
|
53
|
+
# << QString("002|%1").arg(tr("Bagged Goods"))
|
54
|
+
# << QString("003|%1").arg(tr("Suitcase"))
|
55
|
+
# << QString("004|%1").arg(tr("Envelope"))
|
56
|
+
# << QString("005|%1").arg(tr("Golf Bag"))
|
57
|
+
# << QString("006|%1").arg(tr("Skis"))
|
58
|
+
# << QString("007|%1").arg(tr("Snowboard"))
|
59
|
+
# << QString("008|%1").arg(tr("Other"))
|
60
|
+
delivery_speeds = ["000", "001", "002", "003", "004", "005"]
|
61
|
+
# << QString("|")
|
62
|
+
# << QString("000|%1").arg(tr("Courier Service"))
|
63
|
+
# << QString("001|%1").arg(tr("Supermarket"))
|
64
|
+
# << QString("002|%1").arg(tr("Immediate Flight"))
|
65
|
+
# << QString("003|%1").arg(tr("Air Mail (next day delivery)"))
|
66
|
+
# << QString("004|%1").arg(tr("Air Mail (next morning delivery)"))
|
67
|
+
# << QString("005|%1").arg(tr("\"Just Time\" Flight"))
|
68
|
+
delivery_types = ["001", "002", "003"]
|
69
|
+
# << QString("|")
|
70
|
+
# << QString("001|%1").arg(tr("Regular"))
|
71
|
+
# << QString("002|%1").arg(tr("Cool Shipping"))
|
72
|
+
# << QString("003|%1").arg(tr("Frozen Shipping"))
|
73
|
+
time_types = ["01", "12", "14", "16", "04"]
|
74
|
+
# << QString("|")
|
75
|
+
# << QString("01|%1").arg(tr("09:00-12:00"))
|
76
|
+
# << QString("12|%1").arg(tr("12:00-14:00"))
|
77
|
+
# << QString("14|%1").arg(tr("14:00-16:00"))
|
78
|
+
# << QString("16|%1").arg(tr("16:00-18:00"))
|
79
|
+
# << QString("04|%1").arg(tr("18:00-21:00"))
|
80
|
+
seal_types = ["001", "002", "005", "007", "008", "016"]
|
81
|
+
# << QString("|")
|
82
|
+
# << QString("001|%1").arg(tr("Cool Shipping"))
|
83
|
+
# << QString("002|%1").arg(tr("Frozen Shipping"))
|
84
|
+
# << QString("005|%1").arg(tr("Specific Day Delivery"))
|
85
|
+
# << QString("007|%1").arg(tr("Specifc Time Delivery"))
|
86
|
+
# << QString("008|%1").arg(tr("Cash-On-Delivery"))
|
87
|
+
# << QString("016|%1").arg(tr("Specific Time Delivery (AM)"))
|
88
|
+
|
89
|
+
defaults = options[:default_field_values] || {}
|
90
|
+
|
91
|
+
@field_infos = {
|
92
|
+
address_code: FieldSpec.new("住所録コード", "Address Code", false, 12, Encoding::HALFWIDTH | Encoding::ROMAJI | Encoding::NUMBERS | Encoding::KATAKANA, nil, nil),
|
93
|
+
shipping_phone_number: FieldSpec.new("お届け先電話番号", "Shipping Phone Number", false, 14, Encoding::HALFWIDTH | Encoding::NUMBERS | Encoding::HYPHEN, nil, nil),
|
94
|
+
shipping_postal_code: FieldSpec.new("お届け先郵便番号", "Shipping Postal Code", false, 8, Encoding::HALFWIDTH | Encoding::NUMBERS | Encoding::HYPHEN, nil, nil),
|
95
|
+
shipping_address1: FieldSpec.new("お届け先住所1", "Shipping Address 1", true, 16, Encoding::FULLWIDTH | Encoding::ROMAJI | Encoding::NUMBERS | Encoding::KATAKANA, nil, nil),
|
96
|
+
shipping_address2: FieldSpec.new("お届け先住所2", "Shipping Address 2", false, 16, Encoding::FULLWIDTH | Encoding::ROMAJI | Encoding::NUMBERS | Encoding::KATAKANA, nil, nil),
|
97
|
+
shipping_address3: FieldSpec.new("お届け先住所3", "Shipping Address 3", false, 16, Encoding::FULLWIDTH | Encoding::ROMAJI | Encoding::NUMBERS | Encoding::KATAKANA, nil, nil),
|
98
|
+
shipping_name1: FieldSpec.new("お届け先名称1", "Shipping Name 1", true, 16, Encoding::FULLWIDTH | Encoding::ROMAJI | Encoding::NUMBERS | Encoding::KATAKANA, nil, nil),
|
99
|
+
shipping_name2: FieldSpec.new("お届け先名称2", "Shipping Name 2", false, 16, Encoding::FULLWIDTH | Encoding::ROMAJI | Encoding::NUMBERS | Encoding::KATAKANA, nil, nil),
|
100
|
+
shipping_customer_admin_number: FieldSpec.new("お客様管理ナンバー", "Shipping Customer Admin Number", false, 16, Encoding::HALFWIDTH | Encoding::ROMAJI, nil, nil),
|
101
|
+
customer_code: FieldSpec.new("お客様コード", "Customer Code", false, 12, Encoding::HALFWIDTH | Encoding::NUMBERS, nil, defaults[:customer_code]),
|
102
|
+
person_and_division_in_charge: FieldSpec.new("部署・担当者", "Person And Division In Charge", false, 16, Encoding::FULLWIDTH | Encoding::ROMAJI | Encoding::NUMBERS | Encoding::KATAKANA, nil, nil),
|
103
|
+
shipping_persons_number: FieldSpec.new("荷送人電話番号", "Shipping Persons Number", false, 14, Encoding::HALFWIDTH | Encoding::NUMBERS | Encoding::HYPHEN, nil, defaults[:shipping_persons_number]),
|
104
|
+
shipping_requestors_phone_number: FieldSpec.new("ご依頼主電話番号", "Shipping Requestors Phone Number", false, 14, Encoding::HALFWIDTH | Encoding::NUMBERS | Encoding::HYPHEN, nil, defaults[:shipping_requestors_phone_number]),
|
105
|
+
shipping_requestors_postal_code: FieldSpec.new("ご依頼主郵便番号", "Shipping Requestors Postal Code", false, 8, Encoding::HALFWIDTH | Encoding::NUMBERS | Encoding::HYPHEN, nil, defaults[:shipping_requestors_postal_code]),
|
106
|
+
shipping_requestors_address_line_1: FieldSpec.new("ご依頼主住所1", "Shipping Requestors Address Line 1", false, 16, Encoding::FULLWIDTH | Encoding::ROMAJI | Encoding::NUMBERS | Encoding::KATAKANA, nil, defaults[:shipping_requestors_address_line_1]),
|
107
|
+
shipping_requestors_address_line_2: FieldSpec.new("ご依頼主住所2", "Shipping Requestors Address Line 2", false, 16, Encoding::FULLWIDTH | Encoding::ROMAJI | Encoding::NUMBERS | Encoding::KATAKANA, nil, defaults[:shipping_requestors_address_line_1]),
|
108
|
+
shipping_requestors_name_line_1: FieldSpec.new("ご依頼主名称1", "Shipping Requestors Name Line 1", false, 16, Encoding::FULLWIDTH | Encoding::ROMAJI | Encoding::NUMBERS | Encoding::KATAKANA, nil, defaults[:shipping_requestors_name_line_1]),
|
109
|
+
shipping_requestors_name_line_2: FieldSpec.new("ご依頼主名称2", "Shipping Requestors Name Line 2", false, 16, Encoding::FULLWIDTH | Encoding::ROMAJI | Encoding::NUMBERS | Encoding::KATAKANA, nil, nil),
|
110
|
+
package_code: FieldSpec.new("荷姿コード", "Package Code", false, 3, Encoding::HALFWIDTH | Encoding::NUMBERS, package_codes, defaults[:package_code]),
|
111
|
+
item1: FieldSpec.new("品名1", "Item 1", false, 16, Encoding::FULLWIDTH, nil, nil),
|
112
|
+
item2: FieldSpec.new("品名2", "Item 2", false, 16, Encoding::FULLWIDTH, nil, nil),
|
113
|
+
item3: FieldSpec.new("品名3", "Item 3", false, 16, Encoding::FULLWIDTH, nil, nil),
|
114
|
+
item4: FieldSpec.new("品名4", "Item 4", false, 16, Encoding::FULLWIDTH, nil, nil),
|
115
|
+
item5: FieldSpec.new("品名5", "Item 5", false, 16, Encoding::FULLWIDTH, nil, nil),
|
116
|
+
item_count: FieldSpec.new("出荷個数", "Item Count", false, 3, Encoding::HALFWIDTH | Encoding::NUMBERS, nil, nil),
|
117
|
+
delivery_speed: FieldSpec.new("便種(スピードで選択)", "Delivery Speed", false, 3, Encoding::HALFWIDTH | Encoding::NUMBERS, delivery_speeds, defaults[:delivery_speed]),
|
118
|
+
delivery_type: FieldSpec.new("便種(商品)", "Delivery Type", false, 3, Encoding::HALFWIDTH | Encoding::NUMBERS, delivery_types, defaults[:delivery_type]),
|
119
|
+
delivery_date: FieldSpec.new("配達日", "Delivery Date", false, 8, Encoding::HALFWIDTH | Encoding::NUMBERS, nil, nil),
|
120
|
+
delivery_time1: FieldSpec.new("配達指定時間帯", "Delivery Time 1", false, 2, Encoding::HALFWIDTH | Encoding::NUMBERS, time_types, nil),
|
121
|
+
delivery_time2: FieldSpec.new("配達指定時間(時分)", "Delivery Time 2", false, 4, Encoding::HALFWIDTH | Encoding::NUMBERS, nil, nil),
|
122
|
+
cod_amount: FieldSpec.new("代引金額", "COD Amount", false, 7, Encoding::HALFWIDTH | Encoding::NUMBERS, nil, nil),
|
123
|
+
included_tax_amount: FieldSpec.new("消費税", "Included Tax Amount", false, 6, Encoding::HALFWIDTH | Encoding::NUMBERS, nil, nil),
|
124
|
+
cod_payment_method: FieldSpec.new("決済種別", "COD Payment Method", false, 1, Encoding::HALFWIDTH | Encoding::NUMBERS, nil, defaults[:cod_payment_method]),
|
125
|
+
insured_amount: FieldSpec.new("保険金額", "Insured Amount", false, 8, Encoding::HALFWIDTH | Encoding::NUMBERS, nil, defaults[:insured_amount]),
|
126
|
+
display_insured_amount: FieldSpec.new("保険金額印字", "Display Insured Amount", false, 1, Encoding::HALFWIDTH | Encoding::NUMBERS, nil, defaults[:display_insured_amount]),
|
127
|
+
seal1: FieldSpec.new("指定シール1", "Seal 1", false, 3, Encoding::HALFWIDTH | Encoding::NUMBERS, seal_types, nil),
|
128
|
+
seal2: FieldSpec.new("指定シール2", "Seal 2", false, 3, Encoding::HALFWIDTH | Encoding::NUMBERS, seal_types, nil),
|
129
|
+
seal3: FieldSpec.new("指定シール3", "Seal 3", false, 3, Encoding::HALFWIDTH | Encoding::NUMBERS, seal_types, nil),
|
130
|
+
stops_at_delivery_centre: FieldSpec.new("営業店止め", "Stops At Delivery Centre", false, 1, Encoding::HALFWIDTH | Encoding::NUMBERS, nil, defaults[:stops_at_delivery_centre]),
|
131
|
+
sagawa_logistics_centre: FieldSpec.new("SRC区分", "Sagawa Logistics Centre", false, 1, Encoding::HALFWIDTH | Encoding::NUMBERS, nil, defaults[:sagawa_logistics_centre]),
|
132
|
+
sagawa_centre_code: FieldSpec.new("営業店コード", "Sagawa Centre Code", false, 4, Encoding::HALFWIDTH | Encoding::NUMBERS, nil, nil),
|
133
|
+
payment_style: FieldSpec.new("元着区分", "Payment Style", false, 1, Encoding::HALFWIDTH | Encoding::NUMBERS, nil, defaults[:payment_style])
|
134
|
+
}
|
135
|
+
# e.g., {0 => {shipping_name: Field}}
|
136
|
+
@next_row_id = 0
|
137
|
+
@row_fields = Hash.new { |h, k| h[k] = Hash.new() }
|
138
|
+
end
|
139
|
+
|
140
|
+
def row_ids
|
141
|
+
@row_fields.keys
|
142
|
+
end
|
143
|
+
|
144
|
+
def field_names
|
145
|
+
@field_infos.keys
|
146
|
+
end
|
147
|
+
|
148
|
+
def add_row
|
149
|
+
result = @next_row_id + 1
|
150
|
+
@next_row_id += 1
|
151
|
+
result
|
152
|
+
end
|
153
|
+
|
154
|
+
def set_field_value(row_id, field_name, field_value)
|
155
|
+
row = @row_fields[row_id]
|
156
|
+
field_info = @field_infos[field_name]
|
157
|
+
raise "unrecognised field #{field_name}" if field_info.nil?
|
158
|
+
|
159
|
+
field = Field.new(field_info, field_value)
|
160
|
+
row[field_name] = field
|
161
|
+
end
|
162
|
+
|
163
|
+
def add_row_values(values = {})
|
164
|
+
row_id = add_row
|
165
|
+
values.each do |field_name, field_value|
|
166
|
+
set_field_value(row_id, field_name, field_value)
|
167
|
+
end
|
168
|
+
row_id
|
169
|
+
end
|
170
|
+
|
171
|
+
def get_field_value(row_id, field_name)
|
172
|
+
row = @row_fields[row_id]
|
173
|
+
field_info = @field_infos[field_name]
|
174
|
+
field = row[field_name]
|
175
|
+
if field.nil?
|
176
|
+
field = Field.new(field_info, nil)
|
177
|
+
end
|
178
|
+
field.value || ""
|
179
|
+
end
|
180
|
+
|
181
|
+
def get_field_error(row_id, field_name)
|
182
|
+
row = @row_fields[row_id]
|
183
|
+
field_info = @field_infos[field_name]
|
184
|
+
field = row[field_name]
|
185
|
+
if field.nil?
|
186
|
+
field = Field.new(field_info, nil)
|
187
|
+
end
|
188
|
+
field.encoding_errors || ""
|
189
|
+
end
|
190
|
+
|
191
|
+
def encoding_errors
|
192
|
+
result = {}
|
193
|
+
@row_fields.each do |row_id, fields|
|
194
|
+
errors = fields.select { |_n, f| f.encoding_errors.any? }
|
195
|
+
result[row_id] = errors unless errors.empty?
|
196
|
+
end
|
197
|
+
result
|
198
|
+
end
|
199
|
+
|
200
|
+
def to_csv(options = {})
|
201
|
+
field_headers = @field_infos.map { |_k, v| v.header.encode(::Encoding::SJIS) }
|
202
|
+
::CSV.generate(options) do |csv|
|
203
|
+
csv << field_headers
|
204
|
+
|
205
|
+
@row_fields.each do |row|
|
206
|
+
row_data = field_names.map do |field_name|
|
207
|
+
field_value = get_field_value(row[0], field_name)
|
208
|
+
begin
|
209
|
+
field_value.gsub("−", "‐").encode(::Encoding::SJIS)
|
210
|
+
rescue => ex
|
211
|
+
raise "could not encode field #{field_name} (value #{field_value}) - #{ex.message}"
|
212
|
+
end
|
213
|
+
end
|
214
|
+
csv << row_data
|
215
|
+
end
|
216
|
+
end
|
217
|
+
end
|
218
|
+
end
|
219
|
+
end
|
220
|
+
end
|
@@ -0,0 +1,162 @@
|
|
1
|
+
require 'nkf'
|
2
|
+
|
3
|
+
module JapanShippingCSV
|
4
|
+
module Encoding
|
5
|
+
# Eg. HALFWIDTH + ROMAJI + NUMBERS can be represented by:
|
6
|
+
# valid_encodings = Encoding::HALFWIDTH | Encoding::ROMAJI | Encoding::NUMBERS
|
7
|
+
# and to figure out whether a flag is set:
|
8
|
+
# romaji_allowed? = valid_encodings & Encoding::ROMAJI
|
9
|
+
# 0 = false, 1 = true (which is not true in ruby)
|
10
|
+
HALFWIDTH = 1 # Hankaku
|
11
|
+
FULLWIDTH = 2 # Zenkaku
|
12
|
+
ROMAJI = 4
|
13
|
+
NUMBERS = 8
|
14
|
+
KATAKANA = 16
|
15
|
+
HYPHEN = 32
|
16
|
+
|
17
|
+
module CodePoints
|
18
|
+
# Character set lower/upper bound definitions
|
19
|
+
## Bounds for Hiragana
|
20
|
+
ZENKAKU_HIRAGANA_FIRST = 'ぁ' # U+3041
|
21
|
+
ZENKAKU_HIRAGANA_LAST_FOR_CONVERT = 'ん' # U+3093
|
22
|
+
ZENKAKU_HIRAGANA_LAST = 'ゖ' # U+3096
|
23
|
+
|
24
|
+
## Bounds for Katakana
|
25
|
+
HANKAKU_KATAKANA_FIRST = 'ヲ' # U+FF66
|
26
|
+
HANKAKU_KATAKANA_LAST = 'ン' # U+FF9D
|
27
|
+
|
28
|
+
ZENKAKU_KATAKANA_FIRST = 'ァ' # U+30A1
|
29
|
+
ZENKAKU_KATAKANA_LAST_FOR_CONVERT = 'ン' # U+30F3
|
30
|
+
ZENKAKU_KATAKANA_LAST = 'ヺ' # U+30FA
|
31
|
+
|
32
|
+
## Bounds for Punctuation (kutoten)
|
33
|
+
HANKAKU_PUNCTUATION_FIRST = '。' # U+FF61
|
34
|
+
HANKAKU_PUNCTUATION_LAST = '゚' # U+FF9F
|
35
|
+
HANKAKU_PUNCTUATION_ONBIKI = 'ー' # U+FF70
|
36
|
+
|
37
|
+
ZENKAKU_PUNCTUATION_FIRST = '、' # U+3001
|
38
|
+
ZENKAKU_PUNCTUATION_LAST = '〜' # U+301C
|
39
|
+
ZENKAKU_PUNCTUATION_HG_FIRST = '゛' # U+309B
|
40
|
+
ZENKAKU_PUNCTUATION_HG_LAST = 'ゞ' # U+309E
|
41
|
+
ZENKAKU_PUNCTUATION_KK_FIRST = '・' # U+30FB
|
42
|
+
ZENKAKU_PUNCTUATION_KK_LAST = 'ヾ' # U+30FE
|
43
|
+
|
44
|
+
## Bounds for Numeric
|
45
|
+
HANKAKU_NUMBER_FIRST = '0' # U+0030
|
46
|
+
HANKAKU_NUMBER_LAST = '9' # U+0039
|
47
|
+
|
48
|
+
ZENKAKU_NUMBER_FIRST = '0' # U+FF10
|
49
|
+
ZENKAKU_NUMBER_LAST = '9' # U+FF19
|
50
|
+
|
51
|
+
## Bounds for Alphabetic
|
52
|
+
HANKAKU_LETTER_UPPER_FIRST = 'A' # U+0041
|
53
|
+
HANKAKU_LETTER_UPPER_LAST = 'Z' # U+005A
|
54
|
+
HANKAKU_LETTER_LOWER_FIRST = 'a' # U+0061
|
55
|
+
HANKAKU_LETTER_LOWER_LAST = 'z' # U+007A
|
56
|
+
|
57
|
+
ZENKAKU_LETTER_UPPER_FIRST = 'A' # U+FF21
|
58
|
+
ZENKAKU_LETTER_UPPER_LAST = 'Z' # U+FF3A
|
59
|
+
ZENKAKU_LETTER_LOWER_FIRST = 'a' # U+FF41
|
60
|
+
ZENKAKU_LETTER_LOWER_LAST = 'z' # U+FF5A
|
61
|
+
|
62
|
+
# Bounds for All Alphanumeric and Symbol ASCII
|
63
|
+
HANKAKU_SPACE = ' ' # U+0020
|
64
|
+
HANKAKU_ASCII_FIRST = '!' # U+0021
|
65
|
+
HANKAKU_ASCII_LAST = '~' # U+007E
|
66
|
+
|
67
|
+
ZENKAKU_SPACE = ' ' # U+3000
|
68
|
+
ZENKAKU_ASCII_FIRST = '!' # U+FF01
|
69
|
+
ZENKAKU_ASCII_LAST = '~' # U+FF5E
|
70
|
+
end
|
71
|
+
|
72
|
+
class << self
|
73
|
+
def reencode(value, encoding_flags)
|
74
|
+
return value if value.nil?
|
75
|
+
|
76
|
+
result = value
|
77
|
+
# if half-width not allowed
|
78
|
+
half_width_allowed = (encoding_flags & Encoding::HALFWIDTH) == Encoding::HALFWIDTH
|
79
|
+
if half_width_allowed
|
80
|
+
result = NKF.nkf('-X -w', value).tr('0-9a-zA-Z -', '0-9a-zA-Z -')
|
81
|
+
end
|
82
|
+
# if full-width not allowed
|
83
|
+
fullwidth_allowed = (encoding_flags & Encoding::FULLWIDTH) == Encoding::FULLWIDTH
|
84
|
+
if fullwidth_allowed
|
85
|
+
result = NKF.nkf('-X -w', value).tr('0-9a-zA-Z -', '0-9a-zA-Z -').tr(''', '’')
|
86
|
+
end
|
87
|
+
result
|
88
|
+
end
|
89
|
+
|
90
|
+
def is_romaji(value)
|
91
|
+
return false if value.empty?
|
92
|
+
|
93
|
+
value.split("").each do |c|
|
94
|
+
# return !(::kana::isHankakuLetter(u) || ::kana::isZenkakuLetter(u));
|
95
|
+
is_hankaku_upper = c >= CodePoints::HANKAKU_LETTER_UPPER_FIRST && c <= CodePoints::HANKAKU_LETTER_UPPER_LAST
|
96
|
+
is_hankaku_lower = c >= CodePoints::HANKAKU_LETTER_LOWER_FIRST && c <= CodePoints::HANKAKU_LETTER_LOWER_LAST
|
97
|
+
is_zenkaku_upper = c >= CodePoints::ZENKAKU_LETTER_UPPER_FIRST && c <= CodePoints::ZENKAKU_LETTER_UPPER_LAST
|
98
|
+
is_zenkaku_lower = c >= CodePoints::ZENKAKU_LETTER_LOWER_FIRST && c <= CodePoints::ZENKAKU_LETTER_LOWER_LAST
|
99
|
+
return false if !is_hankaku_upper && !is_hankaku_lower && !is_zenkaku_upper && !is_zenkaku_lower
|
100
|
+
end
|
101
|
+
true
|
102
|
+
end
|
103
|
+
|
104
|
+
def is_number(value)
|
105
|
+
return false if value.empty?
|
106
|
+
|
107
|
+
value.split("").each do |c|
|
108
|
+
is_hankaku_number = c >= CodePoints::HANKAKU_NUMBER_FIRST && c <= CodePoints::HANKAKU_NUMBER_LAST
|
109
|
+
is_zenkaku_number = c >= CodePoints::ZENKAKU_NUMBER_FIRST && c <= CodePoints::ZENKAKU_NUMBER_LAST
|
110
|
+
return false if !is_hankaku_number && !is_zenkaku_number
|
111
|
+
end
|
112
|
+
true
|
113
|
+
end
|
114
|
+
|
115
|
+
def is_katakana(value)
|
116
|
+
return false if value.empty?
|
117
|
+
|
118
|
+
value.split("").each do |c|
|
119
|
+
is_hankaku_katakana = c >= CodePoints::HANKAKU_KATAKANA_FIRST && c <= CodePoints::HANKAKU_KATAKANA_LAST && c != CodePoints::HANKAKU_PUNCTUATION_ONBIKI
|
120
|
+
is_zenkaku_katakana = c >= CodePoints::ZENKAKU_KATAKANA_FIRST && c <= CodePoints::ZENKAKU_KATAKANA_LAST
|
121
|
+
return false if !is_hankaku_katakana && !is_zenkaku_katakana
|
122
|
+
end
|
123
|
+
true
|
124
|
+
end
|
125
|
+
|
126
|
+
def is_hyphen(value)
|
127
|
+
return false if value.empty?
|
128
|
+
|
129
|
+
value.split("").each do |c|
|
130
|
+
if c != '-' && c != '-' && c != 'ー' && c != 'ー'
|
131
|
+
return false
|
132
|
+
end
|
133
|
+
end
|
134
|
+
true
|
135
|
+
end
|
136
|
+
|
137
|
+
def is_valid_string(value, encoding_flags)
|
138
|
+
value.split("").each do |c|
|
139
|
+
# if is_half_width(c) && !(encoding_flags & Encoding::HALFWIDTH)
|
140
|
+
# return false
|
141
|
+
# end
|
142
|
+
# if is_full_width(c) && !(encoding_flags & Encoding::FULLWIDTH)
|
143
|
+
# return false
|
144
|
+
# end
|
145
|
+
if is_romaji(c) && !(encoding_flags & Encoding::ROMAJI)
|
146
|
+
return false
|
147
|
+
end
|
148
|
+
if is_number(c) && !(encoding_flags & Encoding::NUMBERS)
|
149
|
+
return false
|
150
|
+
end
|
151
|
+
if is_katakana(c) && !(encoding_flags & Encoding::KATAKANA)
|
152
|
+
return false
|
153
|
+
end
|
154
|
+
if is_hyphen(c) && !(encoding_flags & Encoding::HYPHEN)
|
155
|
+
return false
|
156
|
+
end
|
157
|
+
end
|
158
|
+
return true
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|
metadata
ADDED
@@ -0,0 +1,102 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: japan_shipping_csv
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.2.2
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Shaun Cechner
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2020-06-22 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.16'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.16'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '10.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '10.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: minitest
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '5.0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '5.0'
|
55
|
+
description:
|
56
|
+
email:
|
57
|
+
- shaun@brewkeeper.com.au
|
58
|
+
executables: []
|
59
|
+
extensions: []
|
60
|
+
extra_rdoc_files: []
|
61
|
+
files:
|
62
|
+
- ".gitignore"
|
63
|
+
- ".travis.yml"
|
64
|
+
- CHANGELOG.md
|
65
|
+
- CODE_OF_CONDUCT.md
|
66
|
+
- Gemfile
|
67
|
+
- Gemfile.lock
|
68
|
+
- README.md
|
69
|
+
- Rakefile
|
70
|
+
- bin/console
|
71
|
+
- bin/setup
|
72
|
+
- japan_shipping_csv.gemspec
|
73
|
+
- lib/japan_shipping_csv.rb
|
74
|
+
- lib/japan_shipping_csv/ehiden.rb
|
75
|
+
- lib/japan_shipping_csv/encoding.rb
|
76
|
+
- lib/japan_shipping_csv/version.rb
|
77
|
+
homepage: https://gitlab.com/brewkeeper/japan-shipping-csv
|
78
|
+
licenses: []
|
79
|
+
metadata:
|
80
|
+
homepage_uri: https://gitlab.com/brewkeeper/japan-shipping-csv
|
81
|
+
changelog_uri: https://gitlab.com/brewkeeper/japan-shipping-csv/-/blob/master/CHANGELOG.md
|
82
|
+
post_install_message:
|
83
|
+
rdoc_options: []
|
84
|
+
require_paths:
|
85
|
+
- lib
|
86
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
87
|
+
requirements:
|
88
|
+
- - ">="
|
89
|
+
- !ruby/object:Gem::Version
|
90
|
+
version: '0'
|
91
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
92
|
+
requirements:
|
93
|
+
- - ">="
|
94
|
+
- !ruby/object:Gem::Version
|
95
|
+
version: '0'
|
96
|
+
requirements: []
|
97
|
+
rubyforge_project:
|
98
|
+
rubygems_version: 2.7.8
|
99
|
+
signing_key:
|
100
|
+
specification_version: 4
|
101
|
+
summary: Export orders to Japan Shipping Carrier compatible CSV.
|
102
|
+
test_files: []
|