module CommLogistics::Base::Model
  #
  #上位クラス(Sale, Order, Purchase...)共通
  #
  class Superior < LogisticsModel
    self.abstract_class = true
    include Comm::Module::Model::InvalidFlagCd
    include Comm::Module::Model::Revision
    
    # override method (in transaction)
    def create_exec(params)
      main = params[:main]
      parameter_checks(main, params[:details])
      @details_logging = false
      @logging_after_main_saved = "log_create"
      
      add_revision(main)
      create_exec_do(main, params[:details])
      register_lock
      update_parent_rels(main)
      post_checks
      true
    end
    # auto_flow 正常系
    def create_exec_auto_flow(params)
      main = params[:main]
      parameter_checks(main, params[:details])
      @details_logging = false
      @logging_after_main_saved = "log_create"
      
      add_revision(main)
      create_exec_do_auto_flow(main, params[:details])
      register_lock
      update_parent_rels(main)
      post_checks
    end
    def create_exec_do_auto_flow(main, details)
      create_exec_do(main, details)
    end
    # auto_flow auto_flag_code=false時
    def create_not_auto_flow(params)
      params[:main]['state_code'] = MCODE_STATUS2_INCOMP
      create_exec_auto_flow(params)
    end
    def update_exec(params)
      main = params[:main]
      parameter_checks(main, params[:details])
      @details_logging = true
      @logging_before_main_save = "log_update"
      
      @refresh_price = false
      record_checks
      destroy_exec_do
      
      @refresh_price = true
      add_revision(main)
      create_exec_do(main, params[:details])
      update_parent_rels(main)
      post_checks
      true
    end
    
    def destroy_exec
      #transactionの中に入れないとRollbackしてくれないのでコントーラからこちらに移動
      register_unlock(self.id, self.invalid_flag_code == MCODE_FLAG_ON)
      @details_logging = false
      @logging_after_main_saved = "log_destroy"
      add_revision_for_model(self)
      record_checks
      destroy
      destroy_exec_do
      update_parent_rels(self)
      post_checks
      true
    end
    
    def recover_exec
      self.transaction do
        #transactionの中に入れないとRollbackしてくれないのでコントーラからこちらに移動
        register_unlock(self.id, self.invalid_flag_code == MCODE_FLAG_ON)
        @details_logging = true
        @logging_before_main_save = "log_update"
        
        #create_exec_do(self, self.child_details.ext_hashfy)
        add_revision_for_model(self)
        record_checks
        recover
        child_hash = self.child_details.ext_hashfy if respond_to?(:child_details)
        update_account_info(self, child_hash) if respond_to?(:update_account_info)
        update_stock_info(self, child_hash) if respond_to?(:update_stock_info)
        update_products_price_info(self, child_hash) if respond_to?(:update_products_price_info)
        update_parent_rels(self)
        post_checks
        true
      end
    end
    # トランザクション内で関連処理の親のレコードを更新する処理
    # 必要に応じてoverrideしましょう
    def update_parent_rels(main)
    end
    # トランザクション内で最後に走るチェック
    # 必要に応じてoverrideしましょう
    def post_checks
    end
    #引数チェック
    def parameter_checks(main, details)
    end
    #更新対象レコードチェック
    def record_checks
    end
    
    def logging_call(method_name)
      @log_id = eval(method_name) if respond_to?(method_name.to_sym)
    rescue => e
      logger.error("fail to logging:" + method_name)
      raise e
    end
    
    # callback to update details
    def update_details(parent_id, details_params)
      # detail instanceを作っていろいろセット
      detail_ins = detail_class.new
      detail_ins.log_id = @log_id
      detail_ins.session = @session
      detail_ins.children_logging = @details_logging
      detail_ins.parent_key = self.class.name.foreign_key
      add_seq_number(details_params)
      unless detail_ins.update_children(parent_id, details_params)
        raise EMJ0003 + EMD0002
      end
    end
    def detail_class
      eval("#{self.class.to_s}Detail")
    end
    
    def add_seq_number(params)
      num = 1
      params.each do |p|
        p['seq_number'] = num
        num += 1
      end
    end
    
    # 取扱注意...
    def save(with_logging=true)
      logging_call(@logging_before_main_save) if with_logging && @logging_before_main_save
      ret = super()
      logging_call(@logging_after_main_saved) if with_logging && @logging_after_main_saved && ret
      return ret
    end
    
    def save_to_get_id
      save(false)
    end
    
    # linkageの正規化
    # 必要な場合はoverrideしていじりましょう
    def self.linkage_standerdize(record, link)
      link
    end
    
    def self.get_comp_total_quantity(id, par=nil)
      ar = find(id, :select=>"total_quantity, state_code")
      return ar && ar.state_code==MCODE_STATUS2_COMP ? ar.total_quantity : 0
    end
    
    #非在庫管理品の合計本数を求める関数
    def self.set_stock_total_quantity(table_params, details)
      total_quantity_for_non_stock = 0
      details.each do |d|
        total_quantity_for_non_stock = total_quantity_for_non_stock + d['quantity'].to_i unless d['stock_flag_code']==MCODE_STOCK_FLAG_ON
      end
      table_params['stock_total_quantity'] = table_params['total_quantity'].to_i - total_quantity_for_non_stock
    end
    
    def complete?
      if self.state_code and self.state_code == MCODE_STATUS2_COMP
        true
      else
        false
      end
    end
  end
end
