class CustomersLedgersDetailsController < CommLogistics::Base::Controller::ListController
  #初期化
  def initialize
    @mcls = CustomerLedger
    @pdf_cls = CustomersLedgersDetailsPdf
    @pdf_sort_column = 'target_date'
  end
  #print_sheetアクション
  def print_sheet
    params[:show_all]=true
    params[:record_list]={}
    params[:id_list].split(",").each do | id |
      params[:customer_ledger_id] = id
      params[:record_list].store(id.to_i,get_record_list.ext_hashfy({:disp => {:disp_keys => params[:print_disp_keys] || {} }}))
    end
    print_sheet_base
  end
  #印刷前のSQL
  def get_record_list
    @control_keys = 'customers_ledgers_details'
    ss = CustomersLedgersDetailsSearch.new
    ars = ss.search(FLAG_ON, CustomerLedger, [], params)
    return ars
  end
  
  class CustomersLedgersDetailsSearch < Comm::Tool::SqlSearch
    def get_columns_and_tables(tab, join_lists, params, str_vals)
      quantity_sql = "IFNULL(sd.quantity, 1)"
      str_cols = " cl.customer_id,
                   cl.customer_group_id,
                   cl.pre_total,
                   cl.total,
                   cl.total_duty as summed_duty,
                   ( CASE WHEN cld.trade_id > 0 THEN 'sales' WHEN cld.payment_id > 0 THEN 'receivings' WHEN cld.carry_id > 0 THEN 'receivable_carry_remains' END) AS trans_type,
                   ( CASE WHEN cld.trade_id > 0 THEN cld.trade_id WHEN cld.payment_id > 0 THEN cld.payment_id WHEN cld.carry_id > 0 THEN cld.carry_id END) AS trans_id,
                   ( CASE WHEN cld.trade_id > 0 THEN sd.seq_number WHEN cld.payment_id > 0 THEN rd.seq_number WHEN cld.carry_id > 0 THEN 1 END) AS seq_number,
                   ( CASE WHEN cld.trade_id > 0 THEN s.target_date WHEN cld.payment_id > 0 THEN r.target_date WHEN cld.carry_id > 0 THEN cr.target_date END) AS target_date,
                   IF(cld.trade_id > 0, s.customer_id, cl.customer_id) AS sale_customer_id,
                   s.warehouse_id,
                   s.total_duty,
                   s.duty_calc_type_code,
                   sd.product_set_id,
                   sd.product_id,
                   sd.lot_number,
                   sd.serial_number,
                   sd.ubd,
                   sd.quantity,
                   sd.price,
                   (CASE s.price_fraction_method_code 
                            WHEN #{MCODE_FRACTION_METHOD_FLOOR} THEN TRUNCATE(#{quantity_sql} * sd.price,0)
                            WHEN #{MCODE_FRACTION_METHOD_CEIL}  THEN TRUNCATE(IF(#{quantity_sql} * sd.price >= 0, #{quantity_sql} * sd.price + 0.9, #{quantity_sql} * sd.price - 0.9),0)
                            WHEN #{MCODE_FRACTION_METHOD_ROUND} THEN TRUNCATE(IF(#{quantity_sql} * sd.price >= 0, #{quantity_sql} * sd.price + 0.5, #{quantity_sql} * sd.price - 0.5),0)
                            ELSE 0 END) AS sub_total_price,
                   rd.credit_type_code,
                   rd.amount,
                   cr.total_carry,
                   cr.total_carry_duty,
                   cm.customer_count"
      str_tab =  " FROM customer_ledger_details AS cld 
                   LEFT JOIN customer_ledgers AS cl ON cld.customer_ledger_id=cl.id
                   LEFT JOIN sales AS s ON cld.trade_id=s.id AND cld.trade_id > 0
                   LEFT JOIN sale_details AS sd ON cld.trade_id=sd.sale_id AND cld.trade_id > 0
                   LEFT JOIN receivings AS r ON cld.payment_id=r.id AND cld.payment_id > 0
                   LEFT JOIN receiving_details AS rd ON cld.payment_id=rd.receiving_id AND cld.payment_id > 0
                   LEFT JOIN receivable_carry_remains AS cr ON cld.carry_id=cr.id AND cld.carry_id > 0
                   LEFT JOIN (SELECT charge_customer_id, count(*) AS customer_count FROM master_app_production.customers GROUP BY charge_customer_id) AS cm 
                              ON cm.charge_customer_id = cl.customer_id /* OR cm.charge_customer_id = s.customer_id */
                   WHERE cl.id = #{params[:customer_ledger_id]} ORDER BY sale_customer_id,target_date,trans_id,seq_number"
      return str_cols, str_tab, str_vals
    end
    #空実装
    def set_target_date_to_where(tab, params, str_where)
    end
  end
  
  # 得意先元帳
  class CustomersLedgersDetailsPdf < CommLogistics::Modules::Print::Controller::PdfLedger
    def initialize(params, mcls)
      @pdf_basename = 'customer_ledgers_details'
      @total_columns = [ 'total_duty', 'sub_total_price', 'amount', 'total_carry', 'total_carry_duty']
      @total_title_column = 'product_name'
      @format_price = @total_columns + ['price', 'ledger_remain']
      @format_date = ['target_date']
      @allow_fraction = ['price']
      @ids = params[:id_list].split(",")
      @mcls = mcls if mcls
      #test
      #@print_line_num_per_sheet = 10
      super
    end
    
    #=== column filter
    # * 各レコードの種類・順番で伝票に表示するカラムを指定する定数配列
    # * trans_type_dn, title, product_nameは元データに含まれないのでメソッド中つくるべし
    CF_TITLE = ['target_date', 'trans_type_dn', 'trans_id']
    CF_SALE_TITLE = ['warehouse_dn'] + CF_TITLE
    CF_SALE_PIECE = ['product_name', 'lot_number', 'serial_number', 'ubd', 'quantity', 'price', 'sub_total_price']
    CF_SALE_DUTY = ['title', 'total_duty']
    CF_RECEIVING_PIECE = ['credit_type_dn', 'amount']
    CF_RECEIVING_TITLE = CF_TITLE + CF_RECEIVING_PIECE
    CF_CARRY_PIECE = ['total_carry', 'total_carry_duty']
    CF_CARRY_TITLE = CF_TITLE + CF_CARRY_PIECE
    #=== OPTS
    # * メソッドrecord_array_to_pdata_with_filterに渡すオプション
    # * 多くの場合は↑のFilterと1:1
    # * 伝票に表示させるカラム、タイトル行に移すカラム、積算するカラムなどを指定
    OPTS_CUST_TITLE = {:filter=>['title'], :to_title_column=>'title'}
    OPTS_SALE_TITLE = {:filter=>CF_SALE_TITLE, :to_title_column=>'warehouse_dn'}
    OPTS_SALE_PIECE = {:filter=>CF_SALE_PIECE, :calc_column=>'sub_total_price', :calc_type=>:add}
    OPTS_SALE_DUTY = {:filter=>CF_SALE_DUTY, :to_title_column=>'title', :calc_column=>'total_duty', :calc_type=>:add}
    OPTS_RECEIVING_TITLE = {:filter=>CF_RECEIVING_TITLE, :to_title_column=>'credit_type_dn', :calc_column=>'amount', :calc_type=>:del}
    OPTS_RECEIVING_PIECE = {:filter=>CF_RECEIVING_PIECE, :to_title_column=>'credit_type_dn', :calc_column=>'amount', :calc_type=>:del}
    OPTS_CARRY_TITLE = {:filter=>CF_CARRY_TITLE,  :calc_column=>CF_CARRY_PIECE, :calc_type=>:add}
    OPTS_CARRY_PIECE = {:filter=>CF_CARRY_PIECE, :calc_column=>CF_CARRY_PIECE, :calc_type=>:add}
    
    def one_master(pdata, page, cnt, rec_array)
      page, cnt = init_master_data(pdata, page, cnt, rec_array.first)
      if @return_because_not_target
        return count_to_next_record_with_opts(pdata, page, cnt, true)
      end
      #一個でも請求書合計があったら、summed_dutyを表示する。
      @req_total_flag = false
      rec_array.each_with_index do |rec, ind|
        #必要ならば売上顧客タイトル
        if rec['customer_count'].to_i > 1 && (ind == 0 || (rec_array[ind-1]['sale_customer_id'] != rec['sale_customer_id']))
          rec['title'] = ['[', rec['sale_customer_dn'].strip, ']'].join('  ')
          page, cnt = record_array_to_pdata_with_filter(pdata, rec, page, cnt, OPTS_CUST_TITLE)
        end
        #あとはレコード種別
        case rec['trans_type']
        when 'sales'
          if rec['seq_number'].to_i == 1
            rec['trans_type_dn'] = '売上'
            page, cnt = record_array_to_pdata_with_filter(pdata, rec, page, cnt, OPTS_SALE_TITLE)
          end
          rec['product_name'] = [rec['product_set_dn'], rec['product_dn']].join(' ')
          page, cnt = record_array_to_pdata_with_filter(pdata, rec, page, cnt, OPTS_SALE_PIECE)
          #(税計算が請求合計ではない場合)次レコードが異伝票ならば消費税を表示
          if rec['duty_calc_type_code']==MCODE_CALC_DUTY_REQ_TOTAL
            @req_total_flag = true
          else
            if ((rec_array[ind+1] && rec_array[ind+1]['seq_number'].to_i == 1) || !rec_array[ind+1])
              rec['title'] = '消費税'
              page, cnt = record_array_to_pdata_with_filter(pdata, rec, page, cnt, OPTS_SALE_DUTY)
            end
          end
          #if ((rec_array[ind+1] && rec_array[ind+1]['seq_number'].to_i == 1) || !rec_array[ind+1]) &&
          #   @req_total_duty_calc_weight == nil
          #  rec['title'] = '消費税'
          #  page, cnt = record_array_to_pdata_with_filter(pdata, rec, page, cnt, OPTS_SALE_DUTY)
          #end
        when 'receivings'
          if rec['seq_number'].to_i == 1
            rec['trans_type_dn'] = '入金'
            page, cnt = record_array_to_pdata_with_filter(pdata, rec, page, cnt, OPTS_RECEIVING_TITLE)
          else
            page, cnt = record_array_to_pdata_with_filter(pdata, rec, page, cnt, OPTS_RECEIVING_PIECE)
          end
        when 'receivable_carry_remains'
          if rec['seq_number'].to_i == 1
            rec['trans_type_dn'] = '調整'
            page, cnt = record_array_to_pdata_with_filter(pdata, rec, page, cnt, OPTS_CARRY_TITLE)
          else
            page, cnt = record_array_to_pdata_with_filter(pdata, rec, page, cnt, OPTS_CARRY_PIECE)
          end
        end
        #必要ならば売上顧客小計
        if rec['customer_count'].to_i > 1 && 
          ((rec_array[ind+1] && rec_array[ind+1]['sale_customer_id'] != rec['sale_customer_id']) || !rec_array[ind+1])
          @last_sub_totals ||= {}
          @sub_totals.each do |k, v|
            @last_sub_totals[k] ||= 0
            set_value_to_pdata(pdata, page, cnt, k, v - @last_sub_totals[k])
            @last_sub_totals[k] = v
          end
          set_value_to_pdata(pdata, page, cnt, @total_title_column, '小計')
          page, cnt = count_to_next_record_with_opts(pdata, page, cnt)
        end
      end
      #総計
      @sub_totals.each do |k, v|
        Rails.logger.debug('total at NOT paging - key:'+k.to_s+' val:'+v.to_s)
        set_value_to_pdata(pdata, page, cnt, k, v)
      end
      #if @req_total_duty_calc_weight
      if @req_total_flag
        total_duty = @summed_duty_for_req_total
        set_value_to_pdata(pdata, page, cnt, 'total_duty', total_duty)
      end
      set_value_to_pdata(pdata, page, cnt, @remain_column_name, @total_remain_as_record)
      set_value_to_pdata(pdata, page, cnt, @total_title_column, '請求先計')
      @sub_totals.clear
      @last_sub_totals.clear if @last_sub_totals
      return count_to_next_record_with_opts(pdata, page, cnt, true)
    end
    
    def init_master_data(pdata, page, cnt, rec)
      @master_wide_info = {'customer_id' => rec['customer_id'], 'customer_dn' => rec['customer_dn']}
      @calc_remain = rec['pre_total'].to_i
      @total_remain_as_record = rec['total'].to_i
      @remain_column_name ||= 'ledger_remain'
      #税計算方法が請求合計の場合は係数を設定
      company_ar = Customer.find(rec['customer_id'])
      #set_req_total_duty_calc_weight(company_ar)
      @summed_duty_for_req_total = rec['summed_duty'].to_i
      
      set_value_to_pdata(pdata, page, cnt, 'target_date', '繰越')
      start_date = conv_date(@params[:start_target_date])
      record_date = conv_date(rec['target_date'])
      if record_date < start_date
        set_value_to_pdata(pdata, page, cnt, @remain_column_name, rec['total'])
        page, cnt = count_to_next_record_with_opts(pdata, page, cnt)
        set_value_to_pdata(pdata, page, cnt, 'target_date', '請求先計')
        set_value_to_pdata(pdata, page, cnt, @remain_column_name, rec['total'])
        @return_because_not_target = true
      else
        set_value_to_pdata(pdata, page, cnt, @remain_column_name, rec['pre_total'])
        @return_because_not_target = false
      end
      return count_to_next_record_with_opts(pdata, page, cnt)
    end
  end
end