app/controllers/wkexpense_controller.rb
# ERPmine - ERP for service industry
# Copyright (C) 2011-2020  Adhi software pvt ltd
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.

class WkexpenseController < WktimeController


  menu_item :wktime
  before_action :find_optional_project, :only => [:reportdetail, :report]
  before_action :check_module_permission, :only => [:index]

  accept_api_auth :reportdetail, :index, :edit, :update, :destroy , :delete_entries, :get_currency

  include WkexpenseHelper
  include SortHelper
  helper :sort


  def getLabelforSpField
    l(:field_amount)
  end

  def getCFInRowHeaderHTML
    "wkexpense_cf_in_row_header"
  end

  def getCFInRowHTML
    "wkexpense_cf_in_row"
  end

  def getTFSettingName
    "wkexpense_issues_filter_tracker"
  end

  def showSpentFor
    false
  end

  def getUnit(entry)
    entry.nil? ? number_currency_format_unit : entry[:currency]
  end

  def getUnitDDHTML
    "wkexpense_currency"
  end

  def getUnitLabel
    l(:field_currency)
  end

  def showWorktimeHeader
    false
  end

  def enterCustomFieldInRow(row)
    false
  end

  def maxHour
    0
  end

  def minHour
    0
  end

  def total_all(total)
    total.nil? ? html_hours("%.2f" % 0.00) : html_hours("%.2f" % total)
  end

  def report
    @query = WkExpenseEntryQuery.build_from_params(params, :project => @project, :name => '_')
    scope = expense_entry_scope
    @report = WkexpenseHelper::WKExpenseReport.new(@project, @issue, params[:criteria], params[:columns], scope)
    respond_to do |format|
      format.html { render :layout => !request.xhr? }
      format.csv  { send_data(report_to_csv(@report), :type => 'text/csv; header=present', :filename => 'wkexpense.csv') }
    end
  end

  def delete_entry
    respond_to do |format|
      format.html {
        if delete(params[:id])
          flash[:notice] = l(:notice_successful_delete)
        else
          flash[:error] = l(:error_expense_entry_delete)
        end
        redirect_to :action => 'reportdetail', :project_id => params[:project]
      }
    end
  end

  def textfield_size
	6
  end

  def showClockInOut
	false
  end

  def getNewCustomField
	nil
  end

  def getTELabel
	l(:label_wk_expensesheet)
  end

  def maxHourPerWeek
	0
  end

  def minHourPerWeek
	0
  end

  def get_currency
    wkCurrency = options_for_currency
    currencies = wkCurrency.map { |cur| { value: cur[1], label: cur[0] }}
    render json: currencies
  end

  def setSpentForID(entry, spentForIds, k)
		entry[:spent_for_attributes] = {} if entry[:spent_for_attributes].blank?
    entry[:spent_for_attributes][:id] = spentForIds.present? && spentForIds[k].present? ? spentForIds[k] : nil
  end

  def setSpentFor(entry, teEntry, spentForIds, k)
		spent_for = {spent_type: 'WkExpenseEntry'}
    spent_for[:id] = spentForIds.present? && spentForIds[k].present? ? spentForIds[k] : nil

    spent_for['spent_on_time'] = getDateTime(teEntry.spent_on, 0, 0, 0)
		# save GeoLocation
    saveGeoLocation(spent_for, params[:latitude], params[:longitude])
    teEntry.wkspentfor_attributes = spent_for
  end

  def getModelName
    'WkExpenseEntry'
  end

  def check_module_permission
    unless showExpense
      render_403
      return false
    end
  end

  def issueLogValidation
  end

  def get_approved_leaves
  end

  def get_holiday
  end

private
  def getSpecificField
    "amount"
  end

  def getEntityNames
    ["#{Wkexpense.table_name}", "#{WkExpenseEntry.table_name}"]
  end

  def getQuery(teQuery, ids, from, to, status)
    spField = getSpecificField()
    dtRangeForUsrSqlStr =  "(" + getAllWeekSql(from, to) + ") tmp1"
    teSqlStr = "(" + teQuery + ") tmp2"
    selectStr = "select tmp3.id, tmp3.user_id as user_id , tmp3.spent_on as spent_on, tmp3.#{spField} as #{spField}, tmp3.status as status, tmp3.status_updater as status_updater, tmp3.created_on as created_on, tmp3.currency as currency"
    query = " from (select tmp2.id, tmp1.id as user_id, tmp1.created_on, tmp1.selected_date as spent_on, " +
        "case when tmp2.#{spField} is null then 0 else tmp2.#{spField} end as #{spField}, " +
        "case when tmp2.status is null then 'e' else tmp2.status end as status, tmp2.currency, tmp2.status_updater from "
    query = query + dtRangeForUsrSqlStr + " left join " + teSqlStr
    query = query + " on tmp1.id = tmp2.user_id and tmp1.selected_date = tmp2.spent_on where tmp1.id in (#{ids}) ) tmp3 "
    query = query + " left outer join (select min( #{getDateSqlString('t.spent_on')} ) as min_spent_on, t.user_id as usrid from wk_expense_entries t, users u "
    query = query + " where u.id = t.user_id and u.id in (#{ids}) #{get_comp_condition('t')} #{get_comp_condition('u')}
      group by t.user_id ) vw on vw.usrid = tmp3.user_id "
    query = query + " left join users AS un on un.id = tmp3.user_id " + get_comp_condition('un')
    query = query + getWhereCond(status)
    return [selectStr, query]
  end

  def findBySql(selectStr, query, orderStr)
		spField = getSpecificField()
		@entry_count = findCountBySql(query, WkExpenseEntry)
    setLimitAndOffset()
		rangeStr = formPaginationCondition()
		@entries = TimeEntry.find_by_sql(selectStr + query + orderStr + rangeStr)
		@unit = nil
    @total_hours = findSumBySql(query, spField, WkExpenseEntry)
  end

  def getTEAllTimeRange(ids)
    teQuery = "select v.startday as startday
      from (
        select #{getDateSqlString('t.spent_on')} as startday " +
        "from wk_expense_entries t
        where user_id in (#{ids}) #{get_comp_condition('t')}
      ) v
      group by v.startday order by v.startday"
    WkExpenseEntry.find_by_sql(teQuery)
  end

  def findWkTEByCond(cond)
    @wktimes = Wkexpense.where(cond)
  end

  def getUserwkStatuses
    cond = getCondition('spent_on', @user.id, @startday, @startday+6)
    @userEntries = findEntriesByCond(cond)
    @approvedwkStatuses = @userEntries.joins("LEFT JOIN wk_statuses ON wk_expense_entries.id = wk_statuses.status_for_id #{get_comp_condition('wk_statuses')} ")
      .where("status_for_type='WkExpenseEntry' and wk_statuses.status = 'a'")
      .select("wk_expense_entries.*")
  end

  def getApproverPermProj
    @approverEntries = []
    @approverwkStatuses = []
    approvableProj = @approvable_projects.pluck(:id).join(',')
    if approvableProj.present?
      cond = "spent_on BETWEEN '#{@startday}' AND '#{@startday+6}' AND user_id = #{@user.id} AND wk_expense_entries.project_id IN (#{approvableProj})"
      @approverEntries = findEntriesByCond(cond)
      @approverwkStatuses = @approverEntries.joins("LEFT JOIN wk_statuses ON wk_expense_entries.id = wk_statuses.status_for_id #{get_comp_condition('wk_statuses')} ")
        .where("status_for_type='WkExpenseEntry' and wk_statuses.status = 'a' ")
    end
  end

  def findEntriesByCond(cond)
    #WkExpenseEntry.joins(:project).joins(:activity).joins("LEFT OUTER JOIN issues ON issues.id = wk_expense_entries.issue_id").where(cond).order('projects.name, issues.subject, enumerations.name, wk_expense_entries.spent_on')
    @renderer.getSheetEntries(cond, WkExpenseEntry, getFiletrParams)
  end

  def setValueForSpField(teEntry,spValue,decimal_separator,entry)
    teEntry.amount = spValue.blank? ? nil : spValue.gsub(decimal_separator, '.').to_f
    teEntry.currency = getUnit(entry)
  end

  def getWkEntity
    Wkexpense.new
  end

  def getTEEntry(id)
    id.blank? ? WkExpenseEntry.new : WkExpenseEntry.find(id)
  end

  def deleteWkEntity(cond)
    Wkexpense.where(cond).delete_all
  end

  def delete(ids)
    #WkExpenseEntry.delete(ids)
    errMsg = false
    @expense_entries = WkExpenseEntry.where(:id => ids)#WkExpenseEntry.find_by_sql("SELECT * FROM wk_expense_entries w where id = #{ids} ;")
    destroyed = WkExpenseEntry.transaction do
      @expense_entries.each do |t|
        status = getExpenseEntryStatus(t.spent_on, t.user_id)
        if !status.blank? && ('a' == status || 's' == status || 'l' == status)
            errMsg = false
        else
          errMsg = true
          WkExpenseEntry.delete(ids)
          break
        end
      end
    end
    errMsg
  end

  def findTEEntries(ids)
    WkExpenseEntry.find(ids)
  end

  def setTotal(wkEntity,total)
    wkEntity.amount = total
  end

  def setEntityLabel
    l(:label_wkexpense)
  end

  def setTEProjects(projects)
    expense_project_ids =  Setting.plugin_redmine_wktime['wkexpense_projects']
    if(!expense_project_ids.blank? && expense_project_ids != [""])
      #expense_projects = Project.find_all_by_id(expense_project_ids)
      expense_projects = Project.find(expense_project_ids)
      projects = projects & expense_projects
    end
    projects
  end

  def find_optional_project
    if !params[:issue_id].blank?
      @issue = Issue.find(params[:issue_id])
      @project = @issue.project
    elsif !params[:project_id].blank?
      @project = Project.find(params[:project_id])
    end
  end

  def validateEntry(stDate)
    nil
  end

  def getTEName
    "expense"
  end

  # Returns the ExpenseEntry scope for index and report actions
  def expense_entry_scope(options={})
    scope = @query.results_scope(options)
    if @issue
      scope = scope.on_issue(@issue)
    end
    scope
  end

  def findTEEntryBySql(query)
    WkExpenseEntry.find_by_sql(query)
  end

  def formQuery(wkSelectStr, sqlStr, wkSqlStr)
    wkSelectStr + " ,exp.currency" + sqlStr + " inner join wk_expense_entries exp on v1.id = exp.id #{get_comp_condition('exp')} " + wkSqlStr
  end

  def getUserCFFromSession
    #return user custom field filters from session
    session[:wkexpense][:filters]
  end

  def getUserIdFromSession
    #return user_id from session
    session[:wkexpense][:user_id]
  end

  def get_statusFromSession
    session[:wkexpense][:status]
  end

  def setUserIdsInSession(ids)
    session[:wkexpense][:all_user_ids] = ids
  end

  def getUserIdsFromSession
    session[:wkexpense][:all_user_ids]
  end

  def getLastPDFCell(list, entry)
    list << [ entry.currency.to_s + " " + entry.amount.to_s , 40 ]
    list
  end

	def getPDFFooter(pdf, row_Height)
		pdf.RDMCell( 140, row_Height, l(:label_total), 1, 0, 'R', 1)
		pdf.RDMCell( 40, row_Height, (@total_hours || 0).to_s, 1, 0, '', 1)
	end
end
