module CommLogistics::Base::Controller
  #
  #上位クラス(SalesController, OrdersController, PurchasesController...)共通
  #
  class Superior < LogisticsController
    require 'json'
    include Comm::Module::Controller::Revision
    include Comm::Module::Controller::InvalidFlagCd
    
    before_filter :set_details, :only => [:create, :update]
    before_filter :set_product_params, :only => [:create, :update]
    before_filter :set_additional, :only => [:create, :update, :delete]
    
    def create
      check_parent_revision
      @table_params[:invalid_flag_code] = MCODE_FLAG_OFF
      ar = @mcls.new
      ar.parent = @parent
      ar.session = session
      ar.additional = @additional
      result = ar.create_mng({:main => @table_params, :details => @details}, params[:master_rev])
      render :json => Comm::Tool::Json.result_json(result, ar.errmsg, get_respons(ar))
    rescue => e
      logger.error(e.message + "\n" + e.backtrace.join("\n"))
      render :json => Comm::Tool::Json.result_json(false, e.message, get_respons(ar))
    end
    
    def overwrite_params(base_name, params)
      if params[base_name]['user_id'].to_i != session[:user_id].to_i
        params[base_name]['user_id']=session[:user_id]
        params[base_name]['section_id']=session[:section_ids][0]
      end
    end
    
    def update
      check_parent_revision
      ar = find_one
      ar.parent = @parent
      ar.session = session
      ar.additional = @additional
      base_name = @mcls.to_s.underscore
      overwrite_params(base_name, params)
      
      # 無効フラグがたっていたらスルー
      if ar.invalid_flag_code && (ar.invalid_flag_code.to_i == Comm::Const::MasterCode::MCODE_FLAG_ON)
        logger.debug(" --- Invalid Through on Update Process")
        result = true
      else
        result = ar.update_mng({:main => @table_params, :details => @details}, params[:master_rev])
      end
      check_rels(ar.id)
      render :json => Comm::Tool::Json.result_json(result, ar.errmsg, get_respons(ar))
    rescue => e
      if e.class == Comm::Module::Controller::Revision::LinkageExisting
        result = true
        logger.warn(e.message + "\n" + e.backtrace.join("\n"))
      else
        result = false
        logger.error(e.message + "\n" + e.backtrace.join("\n"))
      end
      render :json => Comm::Tool::Json.result_json(result, e.message, get_respons(ar))
    end
    
    def destroy
      result = false
      ar = find_one
      ar.session = session
      ar.additional = @additional
      #transactionの中にあるため、処理中にエラーが発生してもRollbackしないので、recevoer_exeとdestroy_execにまわす。
      #register_unlock(params[:id], ar.invalid_flag_code == MCODE_FLAG_ON)
      # invalid flag操作
      if ar.invalid_flag_code == MCODE_FLAG_ON
        #recoverはbase_model/generalに_mngが定義されてないので一階層違う
        result = ar.recover_exec
      else
        result = ar.destroy_mng
      end
      render :json => Comm::Tool::Json.result_json(result, ar.errmsg, get_respons(ar))
    rescue => e
      logger.error(e.message + "\n" + e.backtrace.join("\n"))
      render :json => Comm::Tool::Json.result_json(false, e.message, get_respons(ar))
    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 : 関連取引データの更新日時
    #
    def linkage
      rels = get_rels(params[:id])
      result = []
      
      rels.each do |rel|
        class_name = rel.table_name.classify
        record = eval("#{class_name}.find(#{rel.record_id})").only_hashfy
        link = {'table_name' => rel.table_name}
        ['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
         link['trans_type_code'] = record[rel.table_name.singularize + '_type_code'] if record.include?(rel.table_name.singularize + '_type_code');
         
        # 各テーブルで固有の正規化
        eval("#{class_name}.linkage_standerdize(record, link)")
        result << link
      end
      respond_to do |format|
        format.ext_json do
          render :json => result.to_ext_json('linkages', nil)
        end
      end
    end
    
    #画面からのパラメータが足りていない場合(異常系)の保険
    def ext_index
      unless params.include?(:start_target_date)
        today_string = Date.today.to_s
        params[:start_target_date] = today_string
        params[:end_target_date] = today_string
        params[:limit] ||= '100'
        Rails.logger.info('[INFO] Absent start and end_target_date were filled.')
      end
      super
    end
    
    #override===================
    def get_sql_search
      ss = Comm::Tool::SqlSearch.new
      if params[:action] == "with_details" #アクションがwith_details
        column_name_array, non_table_columns = get_columns_for_with_details
        ss.parent_table_columns = column_name_array.join(',')
        ss.non_table_columns = non_table_columns
      end
      return ss
    end
    
#    def get_sql_search_for_with_details
#      column_name_array, non_table_columns = get_columns_for_with_details
#      ss = Comm::Tool::SqlSearch.new
#      ss.parent_table_columns = column_name_array.join(',')
#      ss.non_table_columns = non_table_columns
#      return ss
#    end
    
    def get_columns_for_with_details
      table_name = @mcls.to_s.tableize
      join_id_column = @mcls.name.underscore + "_id"
      column_name_array = []
      non_table_columns = []
      @mcls.column_names.each do |column_name|
        if column_name == join_id_column
          column_name_array << " #{table_name}.#{column_name} AS parent_#{column_name} "
          non_table_columns << "#{table_name}.#{column_name}"
        elsif column_name != "id" && column_name != "created_at" && column_name != "updated_at" #親のID列はのぞく。detailのidと名前がかぶってしまうので、
          column_name_array << " #{table_name}.#{column_name} "
        end
      end
      return column_name_array, non_table_columns
    end
    
    def with_details
      #override base class method
      #def get_sql_search
      #  return get_sql_search_for_with_details
      #end
      set_with_details
      ext_index
    end
    
    def set_with_details
      # 検索(sql_search)で使用する子クラスを設定
      dcls = eval("#{@mcls}Detail")
      @join_mcls = [{:tab => dcls.name.tableize,
                     :cols => dcls.column_names,
                     :join_id => @mcls.name.underscore + "_id"}]
      #logger.debug(@join_mcls[0][:cols].join(" "))
    end
    
  protected
    def get_respons(ar)
      res = {}
      if ar
        res[:rev_number] = ar.rev_number
        res[:invalid_flag_code] = ar.invalid_flag_code
        res[:target_id] = ar.id
        if ar.master_rev
          res.update(ar.master_rev)
        end
        if ar.respond_to?(:additional) and ar.additional
          res[:additional] = ar.additional
        end
      end
      return res
    end
    
    def set_details
      if params[:details]
        @details = JSON.parse(params[:details])
      else
        @details = []
      end
    end
    
    def set_additional
      if params[:additional]
        @additional = params[:additional]
      else
        @additional = {}
      end
    end
    
    def set_product_params
      @details.each do |d|
        comp_product_set_info(d)
        comp_product_info(d)
      end
    end
    
    def comp_product_set_info(params)
      unless params["product_set_id"].blank?
        set = ProductSet.find(params["product_set_id"])
        params["product_category_id"] = set.product_category_id
      end
    end
    
    def comp_product_info(params)
#      if !params["product_id"].blank? && (params["product_id"] != LIST_PRICE)
      unless params["product_id"].blank?
        product = Product.find(params["product_id"])
        params["unit_code"] = product.unit_code
        params["validity_period"] ||= product.validity_period
        #get_details_params_for_stockとupdate_products_priceで使う。
        params["stock_flag_code"] = product.stock_flag_code
      end
    end
  end
end