class SalesController < CommLogistics::Base::Controller::SuperiorStock
  include Comm::Module::Controller::Logging
  include CommLogistics::Modules::Print::Controller
  include CommLogistics::Modules::Controller::ShowFilter
  include CommLogistics::Modules::Controller::ExtIndexFilter
  include CommLogistics::Modules::PartialSql
  
  def initialize
    @mcls = Sale
    @pdf_cls = SalePdfOut
  end
  
  def summary
    require 'config/site_config'
    #初期値準備
    @init_data, @hash = ProductCategory.set(MFIND_V).find(:all, :select => "id AS product_category_id, 0 AS today, 0 AS month, 0 AS average", :order=> 'disp_sort').index_hashfy([], 'product_category_id')
    @init_data = @init_data.add_disp_names
    @all_results = Marshal.load(Marshal.dump(@init_data))
    #sales の元
    sale = Sale.set(MFIND_V).state(Comm::Const::MasterCode::MCODE_STATUS2_COMP)
    #unless params[:bysales]==STR_TRUE
    #  sale = sale.trans_type_except(Comm::Const::MasterCode::MCODE_SALE_TYPE_ADJUST)
    #end
    today = params[:target_date].blank? ? Date.today : Date.parse(params[:target_date])
    @sale_today = sale.date(today.to_s(:db))
    @sale_month = sale.period({:start => today.beginning_of_month.to_s(:db), :end => today.end_of_month.to_s(:db)})
    #未来の売上がないという前提です。
    @monthly_business_days = today.beginning_of_month.range_business_days(today.end_of_month, $NO_HOLIDAY).length
    @active_days = today.beginning_of_month <= Date.today && today.end_of_month >= Date.today ? today.beginning_of_month.range_business_days(Date.today, $NO_HOLIDAY).length : @monthly_business_days
    #営業日数 => 実績ベースのやり方はやめ。0の日が有ったら狂うから。
    #@active_days = @sale_month.find(:all,:select => "target_date",:group  => "target_date").length
    #本日の売上
    today_ars = find_summary(@sale_today)
    today_ars.each do |ar|
      @all_results[@hash[ar.product_category_id.to_i]]['today'] = ar.row_record if @hash[ar.product_category_id.to_i]
    end
    #当月の売上
    month_ars = find_summary(@sale_month)
    month_ars.each do |ar|
      @all_results[@hash[ar.product_category_id.to_i]]['month'] = ar.row_record if @hash[ar.product_category_id.to_i]
      @all_results[@hash[ar.product_category_id.to_i]]['average'] = (ar.row_record.to_f / @active_days.to_f).round(2) if @hash[ar.product_category_id.to_i]
    end
    close_date = TransClose.find_close('sales')
    @results = { 'all' => @all_results, 
                 'sales_areas' => [], 
                 #'close_flag' => SalesClose.find_target_date(today.to_s(:db), MCODE_STATUS2_COMP).length > 0, 
                 'close_flag' => close_date && close_date.close_date && close_date.close_date >= today, 
                 'target_date'=> today.strftime("%Y-%m-%d"),
                 'business_days' => @monthly_business_days,
                 'active_days' => @active_days,
                 'product_categories' => ProductCategory.set(MFIND_V).find(:all, :order=> 'disp_sort').only_hashfy
               }
    #ユーザー
    @sales_areas = UserPosition.sassign("user_id", session[:user_id].to_i).find(:all,:conditions=>['sales_area_id > 0'],:select => "sales_area_id")
    if @sales_areas.length > 0
      #エリアのラベル
      @results['sales_areas'] = @sales_areas.only_hashfy.add_disp_names
      #エリアの集計
      @area_results = Marshal.load(Marshal.dump(@init_data))
      today_area_ars = find_summary(@sale_today.passign("sales_area_id", @sales_areas.extract("sales_area_id")))
      today_area_ars.each do |ar|
        @area_results[@hash[ar.product_category_id.to_i]]['today'] = ar.row_record if @hash[ar.product_category_id.to_i]
      end
      #当月の売上
      month_area_ars = find_summary(@sale_month.passign("sales_area_id", @sales_areas.extract("sales_area_id")))
      month_area_ars.each do |ar|
        @area_results[@hash[ar.product_category_id.to_i]]['month'] = ar.row_record if @hash[ar.product_category_id.to_i]
        @area_results[@hash[ar.product_category_id.to_i]]['average'] = (ar.row_record.to_f / @active_days.to_f).round(2) if @hash[ar.product_category_id.to_i]
      end
      @results['area'] = @area_results
      
      #個人の集計
      @user_results = Marshal.load(Marshal.dump(@init_data))
      today_user_ars = find_summary(@sale_today.sassign("sales_user_id", session[:user_id]))
      today_user_ars.each do |ar|
        @user_results[@hash[ar.product_category_id.to_i]]['today'] = ar.row_record if @hash[ar.product_category_id.to_i]
      end
      #当月の売上
      month_user_ars = find_summary(@sale_month.sassign("sales_user_id", session[:user_id]))
      month_user_ars.each do |ar|
        @user_results[@hash[ar.product_category_id.to_i]]['month'] = ar.row_record if @hash[ar.product_category_id.to_i]
        @user_results[@hash[ar.product_category_id.to_i]]['average'] = (ar.row_record.to_f / @active_days.to_f).round(2) if @hash[ar.product_category_id.to_i]
      end
      @results['user'] = @user_results
    end
    respond_to do |format|
      format.ext_json do
        render :json => @results
      end
    end
  end
  
  def find_summary(scope)
    conditions = ""
    invalid_flag=false
    filter_flag=false
    if $ENABLE_SUPPLIER_FILTER==true
      if !User.own_user_flag(session[:user_id])
        sids = SuppliersUser.vsuppliers(session[:user_id])
        if sids.blank?
          #なにもないので、無理矢理あり得ないwhereを追加する。
          #conditions += ' sales.invalid_flag_code!=sales.invalid_flag_code '
          invalid_flag=true
        else
          conditions += " sales.supplier_id IN (#{sids.join(',')}) "
          filter_flag=true
        end
      end
    end
    if $ENABLE_CUSTOMER_FILTER==true
      if !User.own_user_flag(session[:user_id])
        cids = CustomersUser.vcustomers(session[:user_id])
        if cids.blank?
          #なにもないので、無理矢理あり得ないwhereを追加する。
          #conditions += ( (conditions.blank? ? "" : " AND ") + ' sales.invalid_flag_code!=sales.invalid_flag_code ')
          invalid_flag=true
        else
          conditions += ( (conditions.blank? ? "" : " AND ") + " sales.customer_id IN (#{cids.join(',')}) ")
          filter_flag=true
        end
      end
    end
    if filter_flag==false && invalid_flag==true
      conditions += ( ' sales.invalid_flag_code!=sales.invalid_flag_code ')
    end
    detail_price, detail_quantity = make_sales_price_and_quantity_cols
    
    if params[:bysales]==STR_TRUE
      record_sql = detail_price.gsub("s.","sales.").gsub("sd.","sale_details.").gsub("AS sale_total_price", "AS row_record")
    else
      record_sql = detail_quantity.gsub("s.","sales.").gsub("sd.","sale_details.").gsub("AS sale_total_quantity", "AS row_record")
    end
    
    return scope.find(:all,
           :joins => :sale_details,
           :select => "product_category_id, #{record_sql}",
           :group  => "sale_details.product_category_id",
           :conditions => [conditions]
           )
  end
  
  class SalePdfOut < PdfBase
    #== PDF作成関連
    def initialize(params, mcls=nil)
      #@print_rec_num_per_sheet = 6
      @params = params
      super
    end
    
    ##２枚用の判定
    def check_two_sheet(ar)
      if ar.sale_sheet_type_code == MCODE_SALE_SHEET_2SHEET_PAYG || ar.sale_sheet_type_code == MCODE_SALE_SHEET_2SHEET_PAYG_AFTER || ar.sale_sheet_type_code == MCODE_SALE_SHEET_2SHEET_STANDARD
        return true
      else
        return false
      end
    end
    
    #ページ数を定義
    def set_print_rec_num_per_sheet(ar)
      if check_two_sheet(ar)
        @print_rec_num_per_sheet = 17
        @print_rec_num_per_sheet_second = 33
      else
        @print_rec_num_per_sheet = 6
      end
      @print_rec_other_info_num = 0
    end
    
    def get_arranged_child_details(ar)
      ##２枚用の設定
      #製品外情報は最後にくるよう明細を分割＆結合(製品外情報はマスターの登録順番に注意！）
      if check_two_sheet(ar)
        details_products = []
        details_other = []
        @detail_product_num = 0
        @detail_other_num = 0
        ar.child_details.each do |dt|
          if dt.stock_flag_code == MCODE_STOCK_FLAG_ON
            details_products << dt
          else
            details_other << dt
          end
          @detail_product_num = details_products.length
          @detail_other_num = details_other.length
        end
        return details_products.concat(details_other)
      else
        return ar.child_details
      end
    end
    
    def make_sheet_add_on_page_end(ar, pdata, page)
      Rails.logger.debug('get_send_info')
      dd = {}
      dd.update(get_send_info(ar))
      dd.update(get_own_info(ar))
      #ページ毎の小計売上金額
      dd['sub_total_price'] = @sub_total
      @sub_total = 0
      #枝番がある場合は伝票番号のうしろにくっつける
      dd['disp_id'] = pdata[page]['id'].to_s
      if pdata[page]['page_total'].to_i > 1
        dd['disp_id'] = [dd['disp_id'], '-', pdata[page]['page_num'].to_s].join('')
      end
      return format_price(dd)
    end
    
    def get_send_info(ar)
      unless @send_info
        if Warehouse.is_own?(ar.warehouse_id)
          tar = Warehouse.find(ar.warehouse_id)
        else
          tar = Customer.find(ar.customer_id)
          tar2 = Warehouse.find(ar.warehouse_id)
        end
        @send_info = { 'send' => get_address_info(tar), 
                       :page_info => {:sheet_type => tar.sale_sheet_type_code}}
        #宛名情報を購入者・届け先情報で上書き
        @send_info = overtype_send_info(ar,@send_info,'send',tar)
        #納品先情報
        if tar2
          @send_info['send_2'] = get_address_info(tar2)
          @send_info = overtype_send_info(ar,@send_info,'send_2',tar2)
        end
        ##２枚用の設定
        if check_two_sheet(ar)
          #2ページ目のフォーマット変更フラグをON
          @send_info[:page_info].store(:next_page,true)
        end
      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})}
        #口座番号は最大5個まで持てる
        customer_ar = Customer.find(ar.customer_id)
        if @params[:enable_charge_options]==STR_TRUE && @params[:account_type_code].to_i > 0
          account_type_code = @params[:account_type_code]
        elsif customer_ar.respond_to?('account_type_code') && customer_ar['account_type_code'].to_i > 0
          account_type_code = customer_ar.account_type_code.to_s
        else 
          account_type_code = "1"
        end
        @own_info['own']['account_number'] = oar['account_number_' + account_type_code]
      end
      return @own_info
    end
    
    def make_sheet_on_change_parent(ar, pdata, page)
      @send_info = nil
      current_page = page - 1
      if pdata[current_page]
        add = {}
        add['sub_total_tax_price'] =  ar.total_duty
        add['sub_total_with_tax_price'] = ar.total_price + add['sub_total_tax_price']
        add['sub_total_without_tax_price'] = ar.total_price
        pdata[current_page].update(format_price(add))
      end
    end
    
    def make_sheet_add_for_detail(ar, detail_ar)
      if ar.sale_type_code == Comm::Const::MasterCode::MCODE_SALE_TYPE_ADJUST && detail_ar.quantity.blank?
        tmp_total_price = detail_ar.price
      else
        tmp_total_price = detail_ar.price * detail_ar.quantity
      end
      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})
      if @sub_total
        @sub_total += total_price
      else
        @sub_total = total_price
      end
      
      detail_hash = {'total_price'=>total_price}
      unless detail_ar.product_id.blank?
        pd = Product.find(detail_ar.product_id)
        pds = ProductSet.find(detail_ar.product_set_id)
        tmp_p_hash = {'product_set_id'=>pds.id, 'product_id'=>pd.id}
        tmp_p_hash.add_disp_name({:disp_keys => @params[:print_disp_keys] || {}})
        detail_hash['product_number'] = tmp_p_hash['product_dn']#pd.disp_name
        detail_hash['jan'] = pd.jan
        detail_hash['class_risk_code'] = pds.class_risk_code
        #空文字がある場合はnullに置き換えてcompactでnullを除く
        detail_hash['product_info1'] = tmp_p_hash['product_set_dn'] + " ／ " + tmp_p_hash['product_dn']#pds.disp_name + " ／ " + pd.disp_name
        detail_hash['product_info2'] = [pd.jan.blank? ?  nil : pd.jan, tmp_p_hash['product_dn']].compact.join(" ／ ")#[pd.jan.blank? ?  nil : pd.jan, pd.disp_name].compact.join(" ／ ")
        detail_hash['product_info3'] = [pd.product_name.blank? ?  nil : pd.product_name, tmp_p_hash['product_dn']].compact.join(" ／ ")#[pd.product_name.blank? ?  nil : pd.product_name, pd.disp_name].compact.join(" ／ ")
        detail_hash['product_info4'] = [pd.jan.blank? ?  nil : pd.jan, tmp_p_hash['product_set_dn'], tmp_p_hash['product_dn']].compact.join(" ／ ")#[pd.jan.blank? ?  nil : pd.jan, pds.disp_name, pd.disp_name].compact.join(" ／ ")
        detail_hash['product_info5'] = [pd.product_name.blank? ?  nil : pd.product_name, tmp_p_hash['product_set_dn'], tmp_p_hash['product_dn']].compact.join(" ／ ")#[pd.product_name.blank? ?  nil : pd.product_name, pds.disp_name, pd.disp_name].compact.join(" ／ ")
        if pds.price_unique_code == MCODE_PRICE_UNIQUE_PRODUCT_SET
          detail_hash['public_price'] = pds.public_price
        elsif pds.price_unique_code == MCODE_PRICE_UNIQUE_PRODUCT
          detail_hash['public_price'] = pd.public_price
        end
      end
      if ar.sale_type_code == Comm::Const::MasterCode::MCODE_SALE_TYPE_ADJUST
        sale_type_dn = Comm::Tool::DispName::add_disp_name([{"sale_type_code"=>Comm::Const::MasterCode::MCODE_SALE_TYPE_ADJUST}], "sale_type_code")
        detail_hash['jan']=sale_type_dn.first['sale_type_dn']
      end
      return detail_hash
    end
    
    def make_sheet_add_for_main(ar)
      require 'config/site_config.rb'
      add = {}
      #add['cutoff_date'] = ar.get_cutoff_date(ar.target_date, ar.cutoff_date_code, ar.charge_timing_code)
      add['cutoff_date'] = ar['form_cutoff_date']#伝票のパラメータから直接代入する。
      if $PRINT_USER_POSITION_NAME_FOR_SHEET
        if ar.user_position_id
          su = UserPosition.find(ar.user_position_id) 
          add['sales_user_name'] = su ? su.j_name : ''
        end
      else
        if ar.sales_user_id
          su = User.find(ar.sales_user_id) 
          add['sales_user_name'] = su ? su.j_name : ''
        end
      end
      #全ページ設定可能な売上金額総合計(税込)
      add['total_with_tax_price'] = ar.total_price + ar.total_duty
      #購入者情報が使われているとき情報補完を行う
      if ar.buyer_flag == MCODE_STOCK_FLAG_ON
        add = supplement_buyer_and_taker(ar,add)
      end
      #伝票出力日時として当日を表示するとき
      add['creation_date'] = Date.today
      return add
    end    
  end
  #売上と仕入の場合は、comp_product_infoで得られたstock_flag_codeをみて、非在庫管理製品を除いたstock_total_quantityを求める。
  def set_product_params
    super
    @mcls.set_stock_total_quantity(@table_params, @details)
  end
end
