class OrdersController < CommLogistics::Base::Controller::SuperiorOrder
  include Comm::Module::Controller::Logging
  include CommLogistics::Modules::Print::Controller
  include CommLogistics::Modules::Controller::ShowFilter
  include CommLogistics::Modules::Controller::ExtIndexFilter
  
  
  #追加発注のときのパラメータを整形する。
  def create
    if params[:add_order_flag] == STR_TRUE
      begin
        @suppliers = {}
        
        @details.each do |detail|
          supplier_id = detail['supplier_id'].to_i
          unless @suppliers.key?(supplier_id)
            @suppliers.store(supplier_id, {:table_params=>{
                                            'supplier_id'=>detail['supplier_id'],
                                            'payto_supplier_id'=>detail['payto_supplier_id'], 
                                            'order_sheet_type_code'=>detail['order_sheet_type_code'],
                                            'currency_type_code'=>detail['currency_type_code'],
                                            'total_quantity'=>0
                                           }, :details=>[]})
          end
          detail.delete('supplier_id')
          detail.delete('payto_supplier_id')
          detail.delete('order_sheet_type_code')
          detail.delete('currency_type_code')
          detail.delete('unit_price_fraction_method_code')
          @suppliers[supplier_id][:table_params]['total_quantity']+=detail['quantity']
          @suppliers[supplier_id][:details].push(detail)
        end
        @table_params[:invalid_flag_code] = MCODE_FLAG_OFF
        @table_params[:user_id] = session[:user_id]
        @add_order_ids = []
        result = true
        @suppliers.each do |key, value|
          #消費税、合計金額とそれに付随するパラメータを記録する。
          sar = Supplier.find(:first,:conditions=>["id = ? and invalid_flag_code=#{MCODE_FLAG_OFF}", value[:table_params]['payto_supplier_id']])
          value[:table_params]['total_duty'] = CommLogistics::Tools::CalcDuty::calc_total_duty(value[:details], sar)
          value[:table_params]['total_price'] = CommLogistics::Tools::CalcDuty::calc_total(value[:details], sar)
          value[:table_params]['unit_price_fraction_method_code'] = sar[:unit_price_fraction_method_code]
          value[:table_params]['price_fraction_method_code'] = sar[:price_fraction_method_code]
          value[:table_params]['duty_type_code'] = sar[:duty_type_code]
          value[:table_params]['price_duty_type_code'] = sar[:price_duty_type_code]
          value[:table_params]['duty_calc_type_code'] = sar[:duty_calc_type_code]
          value[:table_params]['fraction_method_code'] = sar[:fraction_method_code]
          value[:table_params]['frac_digit_code'] = sar[:frac_digit_code]
          value[:table_params]['duty_rate'] = sar[:duty_rate]
          value[:table_params]['sign_type_code'] = value[:table_params]['total_price'] < 0 ? MCODE_SIGN_TYPE_RED : MCODE_SIGN_TYPE_BLACK
          tmp_table_params = @table_params.merge(value[:table_params])
          @mcls.set_stock_and_rels_total_quantity(tmp_table_params, value[:details])
          ar = @mcls.new
          ar.parent = @parent
          ar.session = session
          result &&= ar.create_mng({:main => tmp_table_params, :details => value[:details]}, params[:master_rev])
          @add_order_ids.push(ar.id)
        end
        render :json => Comm::Tool::Json.result_json(result, "", {:target_ids => @add_order_ids})
      rescue => e
        logger.error(e.message + "\n" + e.backtrace.join("\n"))
        render :json => Comm::Tool::Json.result_json(false, e.message)
      end
    else
      super
    end
  end
  
  def initialize
    @mcls = Order
    @pdf_cls = OrderPdfOut
  end
  
  def find_all_with_progress(flag)
    params[:session_user_id] = session[:user_id]
    ss = OrderSearch.new
    ss.table_alias = {'orders' => 't'}
    return ss.search(flag, Order, [], params)
  end
  
  class OrderSearch < Comm::Tool::SqlSearch
    def get_columns_and_tables(tab, join_lists, params, str_vals)
#      ar = Order.find_by_sql(["SELECT MIN(id) AS min_id, MAX(id) AS max_id FROM orders
#                                     WHERE target_date between ? AND  ? ", params[:start_target_date], params[:end_target_date]])
#      if ar.length > 0
#        min_id = ar[0].min_id.to_i
#        max_id = ar[0].max_id.to_i
#      else
#        min_id = 0;
#        max_id = 0;
#      end
      
      invalid_vals = (!params || params[:with_invalid]==STR_TRUE) ? '0,1' : '0'
      
      str_cols = ' * '
#      str_tab =  " FROM (SELECT 
#                           a.*,
#                           IF(a.order_trigger_code=#{MCODE_ORDER_TRIGGER_ORDER},
#                             IF(a.total_quantity=0,
#                               IF(d.cnt=0,0,IF(d.total_quantity=0,100,50)),
#                               100 * IFNULL(d.total_quantity, 0) /
#                               (t.purchases_cnt * a.total_quantity)
#                             ),
#                           NULL) AS progress
#                         FROM orders AS a 
#                         LEFT JOIN (SELECT order_id, SUM(IF(tr.sign_type_code=0,-1,1) * total_quantity) AS total_quantity, count(*) AS cnt FROM purchases AS p
#                                    LEFT JOIN master_app_production.table_rels AS tr ON p.purchase_type_code=tr.trans_type_code AND tr.table_name='purchases'
#                                    WHERE p.state_code=#{MCODE_STATUS2_COMP} AND p.invalid_flag_code=#{MCODE_FLAG_OFF} AND order_id BETWEEN #{min_id} AND #{max_id}
#                                    GROUP BY order_id
#                                  ) AS d ON a.id=d.order_id 
#                         LEFT JOIN (SELECT 
#                                      order_type_code, 
#                                      SUM(IF(table_name='purchases',1,0)) AS purchases_cnt
#                                    FROM master_app_production.table_rels 
#                                    WHERE invalid_flag_code=#{MCODE_FLAG_OFF} 
#                                    GROUP BY order_type_code
#                                  ) AS t ON a.order_type_code=t.order_type_code  
#                         WHERE a.target_date BETWEEN \"#{params[:start_target_date]}\" AND \"#{params[:end_target_date]}\"
#                           AND a.invalid_flag_code IN (#{invalid_vals})
#                   ) AS t "
      str_tab =  " FROM (SELECT 
                           a.*,
                           IF(a.order_trigger_code=#{MCODE_ORDER_TRIGGER_ORDER},
                             IF(a.rels_total_quantity=0,
                                   a.rels_comp_total_quantity,
                                   100 * IFNULL(a.rels_comp_total_quantity, 0) / a.rels_total_quantity
                             ),
                           NULL) AS progress
                         FROM orders AS a 
                         WHERE a.target_date BETWEEN \"#{params[:start_target_date]}\" AND \"#{params[:end_target_date]}\"
                           AND a.invalid_flag_code IN (#{invalid_vals})
                   ) AS t "
      return str_cols, str_tab, str_vals
    end
    #から実装
    def set_target_date_to_where(tab, params, str_where)
    end
  end
  
  # linkage 下記をかえす
  #  table_name : "orders", "purchases"など関連取引テーブルのテーブル名
  #  id : 関連取引テーブルのid。受注から発注を作ったなら、発注データのID
  #  state_code : 関連テーブルの状態のコード値
  #  invalid_flag_code : 無効フラグ
  #  sign_type_code : 赤黒（あれば）
  #  target_date : 関連取引データの処理日
  #  input_date : 関連取引データの入力日
  #  created_at : 関連取引データの作成日時
  #  updated_at : 関連取引データの更新日時
  #
  #関連進捗率の100％となる本数を計算
  NOT_UPDATE_ACCOUNT_TYPES=[MCODE_PURCHASE_TYPE_EXTEND_UNLOAD,
                            MCODE_PURCHASE_TYPE_EXTEND_LOAD,
                            MCODE_PURCHASE_TYPE_STORING,
                            MCODE_PURCHASE_TYPE_PROCESS_UNLOAD]
  def linkage
    rels = Order.get_all_rels(params[:id])
    result = []
    
    rels.each do |rel|
      link = {'table_name' => rel.table_name, 'progress' => 0}
      if rel.record_id.to_i > 0
        class_name = rel.table_name.classify
        record = eval("#{class_name}.find(#{rel.record_id})").only_hashfy
        ['id', 
         'state_code',
         'invalid_flag_code',
         'sign_type_code',
         'target_date',
         'input_date',
         'created_at',
         'updated_at'].each do |val|
           link[val] = record[val] if record.include?(val)
        end
        #sale_type_codeとかshipping_type_codeとか
        link['trans_type_code'] = record[rel.table_name.singularize + '_type_code'] if record.include?(rel.table_name.singularize + '_type_code');
        #自身のテーブル名がsale_id, purchase_idとか赤黒伝票が有る取引処理この値が0より大きかったら赤黒伝票とわかる
        link['parent_id'] = record[rel.table_name.singularize + '_id'] if record.include?(rel.table_name.singularize + '_id');
        # 各テーブルで固有の正規化
        eval("#{class_name}.linkage_standerdize(record, link)")
        if link['invalid_flag_code']==MCODE_FLAG_OFF
          link['total_quantity']=record['total_quantity']
          order_total = NOT_UPDATE_ACCOUNT_TYPES.include?(link['trans_type_code']) ? rel.stock_total_quantity.to_f : rel.total_quantity.to_f
          if link['state_code']==MCODE_STATUS2_COMP
            if order_total == 0
              link['progress'] = record['total_quantity']==0 ? 100 : 50
            else
              sign = link['trans_type_code']==MCODE_PURCHASE_TYPE_EXTEND_UNLOAD || link['trans_type_code']==MCODE_PURCHASE_TYPE_PROCESS_UNLOAD ? -1: 1
              link['progress'] = ((record['total_quantity'].to_f * sign / order_total ) * 100).round()
            end
            link['comp_quantity']=record['total_quantity']
            #ロットを引き継ぐpurchase_type_codeはdetailをとらない。
          end
          unless link['trans_type_code']==MCODE_PURCHASE_TYPE_EXTEND_UNLOAD || link['trans_type_code']==MCODE_PURCHASE_TYPE_PROCESS_UNLOAD || link['trans_type_code']==MCODE_PURCHASE_TYPE_LENDING
            link['details'] = PurchaseDetail.find(:all, :conditions => [' purchase_id = ? ' , link['id'] ]).ext_hashfy
          end
        end
      end
      result << link
    end
    respond_to do |format|
      format.ext_json do
        render :json => result.to_ext_json('linkages', nil)
      end
    end
  end

  class OrderPdfOut < PdfBase
    require 'date'
    SHEET_TYPE_GENERAL = 1
    SHEET_TYPE_GENERAL_WITH_TOTAL = 2
    SHEET_TYPE_OMKK = 3
    
    def initialize(params, mcls=nil)
      @params = params
      super
    end
    
    #PDF生成
    def set_details_to_pages(ar, pdata, details, detail_name, page)
      sar = Supplier.find(ar.supplier_id)
      sheet_type = sar.order_sheet_type_code
      
      @print_rec_num_per_sheet = 10
      @print_rec_num_index = @print_rec_num_per_sheet - 1
      # ヘッダ情報
      tmp_main = ar.only_hashfy
      tmp_main['grand_total_price'] = ar.total_price.to_i + ar.total_duty.to_i
      main_hash = add_disp_name_to_hash(tmp_main)
      #請求書合計や消費税無しの場合は、消してくれといわれたので。
      if ar.duty_calc_type_code.to_i==MCODE_CALC_DUTY_REQ_TOTAL || ar.duty_calc_type_code.to_i==MCODE_CALC_DUTY_NON
        main_hash.update({'total_duty' => '-', 'grand_total_price'=> '-'})
      end
      main_hash.update({:page_info => {:sheet_type => sheet_type}})
      main_hash.update(get_send_info(ar).dup)
      main_hash.update(get_own_info(ar).dup)
      main_hash.update(add_disp_name_to_hash(make_sheet_add_for_main(ar)))
      
      seq, page_sum, accumulate_pages = 0, 0, 0
      page_org = page
      details.each do |d|
        pdata[page] ||= main_hash.dup
        pdata[page][detail_name] ||= {}
        detail_hash = d.only_hashfy
        pd = Product.find(d.product_id) #JANコードを取ってくる。
        detail_hash['jan'] = pd.jan
        tmp_total_price = d.price ? d.price * d.quantity : 0
        detail_hash['row_total_price'] = CommLogistics::Tools::CalcDuty.calc_decimal(tmp_total_price, {:duty_rate=>0, :fraction_method_code=>ar.price_fraction_method_code.to_i,:frac_digit_code=>1})
        pdata[page][detail_name][seq] = add_disp_name_to_hash(detail_hash)
        #page_sum += d['quantity']
        if seq == @print_rec_num_index
          #子レコード数で改ページ
          pdata[page]['page_num'] = page - page_org + 1
          #pdata[page]['page_sum'] = page_sum
          #accumulate_pages += page_sum
          #pdata[page]['accumulate_pages'] = accumulate_pages
          #枝番付きIDの準備
          pdata[page]['disp_id'] = pdata[page]['id'].to_s
          page_sum = 0
          seq = 0
          page += 1
        else
          seq += 1
        end
      end
      
      #子レコード数が半端な場合、改ページの処理
      unless seq == 0
        pdata[page]['page_num'] = page - page_org + 1
        #pdata[page]['page_sum'] = page_sum
        #accumulate_pages += page_sum
        #pdata[page]['accumulate_pages'] = accumulate_pages
        #枝番付きIDの準備
        pdata[page]['disp_id'] = pdata[page]['id'].to_s
        page += 1
      end
      
      #複数ページに及んだ場合は枝番をつける
      if page_org < (page - 1)
        cnt = 1
        for i in page_org..(page - 1)
          pdata[i]['disp_id'] = [pdata[i]['disp_id'], '-', cnt.to_s].join('')
          if i > 0
            @total_info_eraser ||= {'total_price'=>'-', 'total_duty'=>'-', 'grand_total_price'=>'-'}
            pdata[i].update(@total_info_eraser)
          end
          cnt += 1
        end
      end
      @send_info=nil
      return page
    end
    
    def make_sheet_add_for_main(ar)
      main_add={}
      td = ar.target_date
      td = (td.is_a?(Date)) ? td : Date.new(ar.target_date)
      main_add['target_date_str'] = td.strftime("%B %d, %Y")
      main_add['target_month'] = td.strftime("%B %d")
      
      request_date_time=''
      if ar.arrival_date
        request_date_time = ar.arrival_date.strftime("%m月%d日 ")
      end
      if ar.request_time
        splitted = ar.request_time.split(//)
        if splitted.length == 4
          hour = splitted[0..1].join().to_i
          minute = splitted[2..3].join().to_i
          if minute == 0
            arranged_request_time = hour.to_s + '時'
          else
            arranged_request_time = hour.to_s + '時' + minute.to_s + '分'
          end
          request_date_time += arranged_request_time
        else
          #4文字以外なら怖いので何もしない
          request_date_time += ar.request_time
        end
      end
      main_add['request_date_time'] = request_date_time
      return main_add
    end
    
    def make_sheet_add_for_detail(ar, detail_ar)
      total_price = detail_ar.price ? detail_ar.price * detail_ar.quantity : nil
      pd = Product.find(detail_ar.product_id)
      spec = pd.spec2 + 'x' + pd.spec1 + 'mm' if pd.spec2 && pd.spec1
      detail_hash = {'total_price' => total_price, 'spec' => spec}
      return detail_hash
    end
    
    def get_send_info(ar)
      unless @send_info
        sar = Supplier.find(ar.supplier_id)
        @send_info = { 'send' => get_address_info(sar)}
      end
      return @send_info
    end
    
    def get_own_info(ar)
      unless @own_info
        oar = Supplier.find(OWN_SUPPLIER_ID)
        @own_info = { 'own' => get_address_info(oar, {:title=>false, :avoid_delivery_info=>true})}
        opts={:title=>false}
        if ar.delivery_id
          dar = Delivery.find(ar.delivery_id)
        elsif ar.shipment_customer_id
          dar = Customer.find(ar.shipment_customer_id)
        elsif ar.customer_id
          dar = Customer.find(ar.customer_id)
        elsif ar.warehouse_id
          dar = Warehouse.find(ar.warehouse_id)
          opts.update(:avoid_delivery_info=>true)
        else
          dar = Supplier.find(OWN_SUPPLIER_ID)
        end
        @own_info.update({'delivery' => get_address_info(dar, opts)})
      end
      return @own_info
    end
    
    #空override ページ数を動的に振るため独自で
    def make_all_pages_by_parent(ar, pdata, details, page)
      sar = Supplier.find(ar.supplier_id)
      unless sar.currency_type_code == MCODE_CURRENCY_TYPE_JPN
        @currency_type_name = CodeMaster.find(:first,
                              :select => 'j_name',
                              :conditions => ['code_type_id = ? AND code_number = ? ', Comm::Const::DispName::CODE_MASTER_TYPE_INFO['currency_type_code'], sar.currency_type_code]).j_name
      end
    end
  end
  
end
