super_tools 0.0.1
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.
- 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
         
     |