super_tools 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +8 -0
- data/.travis.yml +7 -0
- data/Gemfile +6 -0
- data/Gemfile.lock +173 -0
- data/LICENSE.txt +21 -0
- data/README.md +39 -0
- data/Rakefile +10 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/lib/super_form/basic.rb +43 -0
- data/lib/super_form/concerns/atomic_save.rb +70 -0
- data/lib/super_form/reform.rb +46 -0
- data/lib/super_formatter/ecan/head.rb +13 -0
- data/lib/super_formatter/ecan/import.rb +13 -0
- data/lib/super_formatter/ecan/row.rb +8 -0
- data/lib/super_formatter/hct/head.rb +14 -0
- data/lib/super_formatter/hct/import.rb +13 -0
- data/lib/super_formatter/hct/row.rb +22 -0
- data/lib/super_formatter/import.rb +15 -0
- data/lib/super_formatter/row.rb +14 -0
- data/lib/super_formatter/shopline/head.rb +26 -0
- data/lib/super_formatter/shopline/import.rb +34 -0
- data/lib/super_formatter/shopline/order.rb +88 -0
- data/lib/super_formatter/shopline/row.rb +8 -0
- data/lib/super_formatter/tcat/head.rb +14 -0
- data/lib/super_formatter/tcat/import.rb +13 -0
- data/lib/super_formatter/tcat/row.rb +22 -0
- data/lib/super_process/core.rb +83 -0
- data/lib/super_spreadsheet/loader.rb +91 -0
- data/lib/super_table/action_view.rb +40 -0
- data/lib/super_table/builder.rb +116 -0
- data/lib/super_table/record.rb +23 -0
- data/lib/super_table/tableable.rb +44 -0
- data/lib/super_table/view_helpers.rb +40 -0
- data/lib/super_tools.rb +41 -0
- data/lib/super_tools/version.rb +3 -0
- data/super_tools.gemspec +48 -0
- metadata +361 -0
@@ -0,0 +1,14 @@
|
|
1
|
+
module SuperFormatter
|
2
|
+
module Hct
|
3
|
+
Head = Struct.new(:data) do
|
4
|
+
def indexes
|
5
|
+
@indexes ||= {
|
6
|
+
global_order_id: data.index('訂單號碼') || data.index('清單編號'),
|
7
|
+
mobile: data.index('收貨人電話') || data.index('收貨人電話1'),
|
8
|
+
recipient: data.index('收貨人') || data.index('收貨人名稱'),
|
9
|
+
tracking_code: data.index('查貨號碼') || data.index('十碼貨號')
|
10
|
+
}
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'super_formatter/row'
|
2
|
+
module SuperFormatter
|
3
|
+
module Hct
|
4
|
+
class Row < ::SuperFormatter::Row
|
5
|
+
|
6
|
+
def tracking_code
|
7
|
+
(find(:tracking_code) || "").gsub("'", '')
|
8
|
+
end
|
9
|
+
|
10
|
+
def mobile
|
11
|
+
@mobile ||= begin
|
12
|
+
text = (find(:mobile) || "").gsub("'", "")
|
13
|
+
if text[0] == '9' && text.length == 9
|
14
|
+
"0#{text}"
|
15
|
+
else
|
16
|
+
text
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module SuperFormatter
|
2
|
+
class Import < SuperProcess::Core
|
3
|
+
init :spreadsheet
|
4
|
+
attr_accessor :head, :rows, :orders
|
5
|
+
|
6
|
+
protected
|
7
|
+
|
8
|
+
def build_rows!(head_klass, row_klass)
|
9
|
+
self.head = head_klass.new(spreadsheet.result.shift)
|
10
|
+
self.rows = spreadsheet.result.map.with_index do |data, i|
|
11
|
+
row_klass.new(data, head.indexes)
|
12
|
+
end.compact
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module SuperFormatter
|
2
|
+
module Shopline
|
3
|
+
Head = Struct.new(:data) do
|
4
|
+
def indexes
|
5
|
+
@indexes ||= {
|
6
|
+
order_id: data.index('訂單號碼'),
|
7
|
+
order_created: data.index('訂單日期'),
|
8
|
+
shipping_method: data.index('送貨方式'),
|
9
|
+
payment_method: data.index('付款方式'),
|
10
|
+
payment_status: data.index('付款狀態'),
|
11
|
+
recipient: data.index('收件人'),
|
12
|
+
mobile: data.index('收件人電話號碼'),
|
13
|
+
store_id: data.index('全家服務編號 / 7-11 店號'),
|
14
|
+
address: data.index('完整地址'),
|
15
|
+
total_order_amount: data.index('訂單合計'),
|
16
|
+
note: data.index('送貨備註'),
|
17
|
+
item_title: data.index('商品名稱'),
|
18
|
+
item_option: data.index('選項'),
|
19
|
+
item_code: data.index('商品貨號'),
|
20
|
+
item_qty: data.index('數量'),
|
21
|
+
item_cost: data.index('商品成本')
|
22
|
+
}
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'super_formatter/import'
|
2
|
+
require 'super_formatter/shopline/head'
|
3
|
+
require 'super_formatter/shopline/row'
|
4
|
+
require 'super_formatter/shopline/order'
|
5
|
+
module SuperFormatter
|
6
|
+
module Shopline
|
7
|
+
class Import < ::SuperFormatter::Import
|
8
|
+
|
9
|
+
callable do
|
10
|
+
build_rows!(Head, Row)
|
11
|
+
|
12
|
+
self.orders = merged_orders!.values
|
13
|
+
|
14
|
+
self.orders
|
15
|
+
end
|
16
|
+
|
17
|
+
protected
|
18
|
+
|
19
|
+
def merged_orders!
|
20
|
+
array = {}
|
21
|
+
rows.each do |row|
|
22
|
+
if array[row.order_id].present?
|
23
|
+
# 存在 Merge Item
|
24
|
+
array[row.order_id].merge!(row)
|
25
|
+
else
|
26
|
+
# 不存在建立 Order
|
27
|
+
array[row.order_id] = Order.new(row)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
array
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,88 @@
|
|
1
|
+
require 'warehouse'
|
2
|
+
module SuperFormatter
|
3
|
+
module Shopline
|
4
|
+
class Order
|
5
|
+
attr_accessor :row
|
6
|
+
attr_accessor :items_array, :warehouse_items
|
7
|
+
|
8
|
+
delegate :recipient, to: :row
|
9
|
+
delegate :mobile, to: :row
|
10
|
+
delegate :total_order_amount, to: :row
|
11
|
+
delegate :store_id, to: :row
|
12
|
+
delegate :note, to: :row
|
13
|
+
|
14
|
+
def order_id
|
15
|
+
row.order_id.gsub("#", '')
|
16
|
+
end
|
17
|
+
|
18
|
+
def initialize(row)
|
19
|
+
self.row = row
|
20
|
+
merge!(row)
|
21
|
+
end
|
22
|
+
|
23
|
+
def provider
|
24
|
+
@provider ||= case
|
25
|
+
when row.shipping_method.include?('7-11')
|
26
|
+
:UNIMART
|
27
|
+
when row.shipping_method.include?('全家')
|
28
|
+
:FAMI
|
29
|
+
when row.shipping_method.include?('新竹')
|
30
|
+
:HCT
|
31
|
+
when row.shipping_method.include?('黑貓')
|
32
|
+
:TCAT
|
33
|
+
else
|
34
|
+
nil
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def ref_id
|
39
|
+
order_id
|
40
|
+
end
|
41
|
+
|
42
|
+
def destination
|
43
|
+
@destination ||= case provider
|
44
|
+
when :UNIMART, :FAMI
|
45
|
+
store_id
|
46
|
+
when :HCT, :TCAT
|
47
|
+
address
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def address
|
52
|
+
row.address.gsub("台灣", "")
|
53
|
+
end
|
54
|
+
|
55
|
+
def order_created_at
|
56
|
+
row.order_created
|
57
|
+
end
|
58
|
+
|
59
|
+
def cash_on_delivery?
|
60
|
+
if row.payment_method.include?('取貨付款')
|
61
|
+
true
|
62
|
+
else
|
63
|
+
false
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def only_delivery?
|
68
|
+
!cash_on_delivery?
|
69
|
+
end
|
70
|
+
|
71
|
+
def paid?
|
72
|
+
row.payment_status == '已付款'
|
73
|
+
end
|
74
|
+
|
75
|
+
def items
|
76
|
+
items_array.join(" ")
|
77
|
+
end
|
78
|
+
|
79
|
+
def merge!(row)
|
80
|
+
self.items_array ||= []
|
81
|
+
self.warehouse_items ||= Warehouse::List.new
|
82
|
+
|
83
|
+
self.items_array << "#{row.item_title}-#{row.item_option}*#{row.item_qty}"
|
84
|
+
self.warehouse_items += Warehouse::Item::Code.new(row.item_code, row.item_code, row.item_qty)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module SuperFormatter
|
2
|
+
module Tcat
|
3
|
+
Head = Struct.new(:data) do
|
4
|
+
def indexes
|
5
|
+
@indexes ||= {
|
6
|
+
global_order_id: data.index('訂單編號'),
|
7
|
+
mobile: data.index('手機(收)'),
|
8
|
+
recipient: data.index('收件人'),
|
9
|
+
tracking_code: data.index('託運單號')
|
10
|
+
}
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'super_formatter/row'
|
2
|
+
module SuperFormatter
|
3
|
+
module Tcat
|
4
|
+
class Row < ::SuperFormatter::Row
|
5
|
+
|
6
|
+
def tracking_code
|
7
|
+
(find(:tracking_code) || "").gsub("'", '')
|
8
|
+
end
|
9
|
+
|
10
|
+
def mobile
|
11
|
+
@mobile ||= begin
|
12
|
+
text = (find(:mobile) || "").gsub("'", "")
|
13
|
+
if text[0] == '9' && text.length == 9
|
14
|
+
"0#{text}"
|
15
|
+
else
|
16
|
+
text
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
require 'virtus'
|
2
|
+
module SuperProcess
|
3
|
+
class Core
|
4
|
+
include ActiveModel::Validations
|
5
|
+
include ActiveSupport::Callbacks
|
6
|
+
include Virtus.model
|
7
|
+
|
8
|
+
ValidError = Class.new(StandardError)
|
9
|
+
|
10
|
+
define_callbacks :validations, :task
|
11
|
+
|
12
|
+
def self.before_call(method_name)
|
13
|
+
set_callback :validations, :before, method_name
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.after_call(method_name)
|
17
|
+
set_callback :validations, :after, method_name
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.before_task(method_name)
|
21
|
+
set_callback :task, :before, method_name
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.after_task(method_name)
|
25
|
+
set_callback :task, :after, method_name
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.init(model_name, &block)
|
29
|
+
attr_accessor model_name
|
30
|
+
|
31
|
+
class_eval(&block) if block_given?
|
32
|
+
|
33
|
+
define_method :initialize do |model|
|
34
|
+
self.send("#{model_name}=", model)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.callable(&block)
|
39
|
+
define_method :call! do |params={}|
|
40
|
+
params.each do |attr, value|
|
41
|
+
public_send("#{attr}=", value) if respond_to?("#{attr}=")
|
42
|
+
end
|
43
|
+
run_callbacks :validations do
|
44
|
+
raise ValidError, "Validation Error" if valid? == false
|
45
|
+
|
46
|
+
run_callbacks :task do
|
47
|
+
instance_eval(&block)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
define_method :call do |params={}|
|
53
|
+
begin
|
54
|
+
@result = call!(params)
|
55
|
+
true
|
56
|
+
rescue ValidError
|
57
|
+
false
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def result
|
63
|
+
@result
|
64
|
+
end
|
65
|
+
|
66
|
+
def error_messages
|
67
|
+
if errors.messages.values.present?
|
68
|
+
errors.messages.values.first.first
|
69
|
+
else
|
70
|
+
""
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def self.method_missing(m, *args, &block)
|
75
|
+
puts "Missing: #{m} -> Context: #{self.inspect}" if Rails.env.development?
|
76
|
+
if block_given?
|
77
|
+
new.public_send(m, *args, &block)
|
78
|
+
else
|
79
|
+
new.public_send(m, *args)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
require 'iconv'
|
2
|
+
require 'csv'
|
3
|
+
require 'roo'
|
4
|
+
require 'roo-xls'
|
5
|
+
module SuperSpreadsheet
|
6
|
+
class Loader < SuperProcess::Core
|
7
|
+
attr_accessor :file_path
|
8
|
+
validate :valid_format
|
9
|
+
|
10
|
+
def self.load!(file)
|
11
|
+
new(file)
|
12
|
+
end
|
13
|
+
|
14
|
+
def initialize(file_path)
|
15
|
+
@file_path = file_path
|
16
|
+
end
|
17
|
+
|
18
|
+
callable do
|
19
|
+
rows
|
20
|
+
end
|
21
|
+
|
22
|
+
def extension
|
23
|
+
::File.extname(file_path).split('.').last.force_encoding('utf-8').downcase
|
24
|
+
end
|
25
|
+
|
26
|
+
def valid_format
|
27
|
+
if rows == false
|
28
|
+
errors.add(:file, '檔案格式錯誤')
|
29
|
+
elsif rows.flatten.empty?
|
30
|
+
errors.add(:file, '檔案內容錯誤,空白檔案')
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def rows
|
35
|
+
@rows ||= rows!
|
36
|
+
end
|
37
|
+
|
38
|
+
protected
|
39
|
+
|
40
|
+
def rows!
|
41
|
+
case extension
|
42
|
+
when 'xls'
|
43
|
+
::Roo::Excel.new(file_path).map { |row| convert_float_to_integer(row) }
|
44
|
+
when 'xlsx'
|
45
|
+
::Roo::Excelx.new(file_path).map { |row| convert_float_to_integer(row) }
|
46
|
+
when 'csv'
|
47
|
+
::CSV.parse(csv_content!)
|
48
|
+
else
|
49
|
+
false
|
50
|
+
end
|
51
|
+
rescue
|
52
|
+
false
|
53
|
+
end
|
54
|
+
|
55
|
+
def csv_content!
|
56
|
+
@decode_csv_content ||= begin
|
57
|
+
csv_content_big5!
|
58
|
+
rescue Iconv::IllegalSequence
|
59
|
+
begin
|
60
|
+
csv_content_big5_hkscs!
|
61
|
+
rescue Iconv::IllegalSequence
|
62
|
+
csv_content
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def csv_content
|
68
|
+
@csv_content ||= File.read(file_path)
|
69
|
+
end
|
70
|
+
|
71
|
+
private
|
72
|
+
|
73
|
+
def csv_content_big5!
|
74
|
+
Iconv.new("utf-8", "Big5//TRANSLIT//IGNORE").iconv(csv_content)
|
75
|
+
end
|
76
|
+
|
77
|
+
def csv_content_big5_hkscs!
|
78
|
+
Iconv.new("utf-8", "Big5-HKSCS//TRANSLIT//IGNORE").iconv(csv_content)
|
79
|
+
end
|
80
|
+
|
81
|
+
def convert_float_to_integer(row)
|
82
|
+
row.map do |cell|
|
83
|
+
if cell.is_a?(Float) && cell = cell.to_i
|
84
|
+
cell.to_i
|
85
|
+
else
|
86
|
+
cell
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|