service_packs_controller.rb 6.36 KB
Newer Older
1
class ServicePacksController < ApplicationController
Khang Le's avatar
Khang Le committed
2
3
4
5
6
7
8
9
10
11
12
13
  # only allow admin
  before_action :require_admin

  # Specifying Layouts for Controllers, looking at OPENPROJECT_ROOT/app/views/layouts/admin
  layout 'admin'

  def index
    @service_packs = ServicePack.all
  end

  def new
    @service_pack = ServicePack.new
14
15
16
    # TimeEntryActivity.shared.count.times {@service_pack.mapping_rates.build}
    @sh = TimeEntryActivity.shared
    @c = TimeEntryActivity.shared.count
Khang Le's avatar
Khang Le committed
17
18
19
20
  end

  def show
    @service_pack = ServicePack.find(params[:id])
21
22
    # controller chooses not to get the thresholds.
    # assume the service pack exists.
23
    # TODO: make a separate action JSON only.
24
    respond_to do |format|
25
      format.json {
26
27
        # the function already converted this to json
        render plain: ServicePackPresenter.new(@service_pack).json_export(:rate), status: 200
28
29
      }
      format.html {
30
        @rates = @service_pack.mapping_rates
31
        @assignments = @service_pack.assigns.where(assigned: true).all
32
        # exs = ExpiredSpMailer.new # never instantiate
33
        # binding.pry
34
        # ExpiredSpMailer.expired_email(User.last, @service_pack).deliver_now
35
      }
36
    end
Khang Le's avatar
Khang Le committed
37
38
39
  end

  def create
40
    mapping_rate_attribute = params['service_pack']['mapping_rates_attributes']
41
    # binding.pry
42
43
    activity_id = []
    mapping_rate_attribute.each {|_index, hash_value| activity_id.push(hash_value['activity_id'])}
44

45
    if activity_id.uniq.length == activity_id.length
46
      @service_pack = ServicePack.new(service_pack_params)
47
48
49
50
51
      # render plain: 'not duplicated'
      if @service_pack.save
        flash[:notice] = 'Service Pack creation successful.'
        redirect_to action: :show, id: @service_pack.id and return
      else
52
53
        flash[:error] = 'Service Pack creation failed.'
        redirect_to action: :new
54
      end
Khang Le's avatar
Khang Le committed
55
    else
56
      # render plain: 'duplicated'
57
58
      flash[:error] = 'Only one rate can be defined to one activity.'
      redirect_to action: :new
Khang Le's avatar
Khang Le committed
59
60
61
    end
  end

Kiet's avatar
Kiet committed
62
  def edit
Tam Le's avatar
Tam Le committed
63
64
65
66
67
    @sp = ServicePack.find_by(params[:id])
    if @sp.nil?
      flash[:error] = "Service Pack not found"
      redirect_to action: :index and return
    end
Kiet's avatar
Kiet committed
68
69
70
    @activity = @sp.time_entry_activities.build
  end

Tam Le's avatar
Tam Le committed
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
  def update
    @sp = ServicePack.find_by(params[:id])
    if @sp.nil?
      flash[:error] = "Service Pack not found"
      redirect_to action: :index and return
    end
    mapping_rate_attribute = params['service_pack']['mapping_rates_attributes']
    activity_id = []
    mapping_rate_attribute.each {|_index, hash_value| activity_id.push(hash_value['activity_id'])}

    if activity_id.uniq.length == activity_id.length
      @sp.update(service_pack_params)
      # render plain: 'not duplicated'
      if @sp.save
        flash[:notice] = 'Service Pack update successful.'
        redirect_to action: :show, id: @sp.id and return
      else
88
        flash.now[:error] = 'Service Pack update failed.'
Tam Le's avatar
Tam Le committed
89
90
91
92
93
        @activity = @sp.time_entry_activities.build
        render 'edit'
      end
    else
      # render plain: 'duplicated'
94
      flash.now[:error] = 'Only one rate can be defined to one activity.'
Tam Le's avatar
Tam Le committed
95
96
97
98
99
      @activity = @sp.time_entry_activities.build
      renders 'edit'
    end
  end

Kiet's avatar
Kiet committed
100
  def destroy
Tam Le's avatar
Tam Le committed
101
102
103
104
105
    @sp = ServicePack.find_by(params[:id])
    if @sp.nil?
      flash[:error] = "Service Pack not found"
      redirect_to action: :index and return
    end
106
107
108
109
110
    if @sp.assigned?
      flash[:error] = "Please unassign this SP from all projects before proceeding!"
      redirect_to action: :show, id: @sp.id and return
    end
    @sp.destroy!
Kiet's avatar
Kiet committed
111
112
113
114

    redirect_to service_packs_path
  end

Tam Le's avatar
Tam Le committed
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131

  # =======================================================
  # :Docs
  # * Limit: Serving JSON only. Must be Admin to access.
  # * Purpose:
  # Return a table with consumed units for a Service Pack grouped by activities and sorted
  # from large to small.
  # * Expected Inputs:
  # [service_pack_id]: Sharing the same route with the resourceful default.
  # Put in the link. Mandatory.
  # [start_period]: Beginning of the counting period. As a date. Optional.
  # [end_period]: Ending of the counting period. As a date. Optional.
  # start_period MUST NOT be later than end_period.
  # Both or none of [start_period, end_period] can be present.
  # * Expected Outputs
  # Top class: None
  # Content: Array of object having [name, consumed]
132
133
  # - consumed: How many units are consumed (in given period)
  # - act_name: Name of activity 
Tam Le's avatar
Tam Le committed
134
135
  # Status: 200
  # * When raising error
Tam Le's avatar
Tam Le committed
136
  # HTTP 404: SP not found
Tam Le's avatar
Tam Le committed
137
138
139
  # HTTP 400: Malformed request.
  # =======================================================

Tam Le's avatar
Tam Le committed
140
  def statistics
141
142
143
144
145
    start_day = params[:start_period]&.to_date # ruby >= 2.3.0
    end_day = params[:end_period]&.to_date
    if start_day.nil? ^ end_day.nil?
      render json: { error: 'GET OUT!'}, status: 400 and return
    end
Tam Le's avatar
Tam Le committed
146
147
148
149

    if !ServicePack.find_by(id: params[:service_pack_id])
      render json: { error: 'NOT FOUND'}, status: 404 and return
    end
150
151
152
153
154

    # Notice: Change max(t3.name) to ANY_VALUE(t3.name) on production builds.
    # MySQL specific >= 5.7.5
    # https://dev.mysql.com/doc/refman/5.7/en/group-by-handling.html

Tam Le's avatar
Tam Le committed
155
156
    get_parent_id = <<-SQL
      SELECT id, name,
157
      CASE WHEN parent_id IS NULL THEN id ELSE parent_id END AS pid
Tam Le's avatar
Tam Le committed
158
      FROM #{TimeEntryActivity.table_name}
159
      WHERE type = 'TimeEntryActivity'
Tam Le's avatar
Tam Le committed
160
161
      SQL
    body_query = <<-SQL
162
      SELECT t3.pid AS act_id, max(t3.name) AS act_name, sum(t1.units) AS consumed
Tam Le's avatar
Tam Le committed
163
164
165
166
      FROM #{ServicePackEntry.table_name} t1
      INNER JOIN #{TimeEntry.table_name} t2
      ON t1.time_entry_id = t2.id
      INNER JOIN (#{get_parent_id}) t3
167
      ON t2.activity_id = t3.id
Tam Le's avatar
Tam Le committed
168
169
      SQL
    group_clause = <<-SQL
170
171
      GROUP BY t3.pid
      ORDER BY consumed DESC
Tam Le's avatar
Tam Le committed
172
      SQL
Tam Le's avatar
Tam Le committed
173
    where_clause = "WHERE t1.service_pack_id = ?"
174
    where_clause << (start_day.nil? ? '' : ' AND t1.created_at BETWEEN ? AND ?')
Tam Le's avatar
Tam Le committed
175
    query = body_query + where_clause + group_clause
176
    # binding.pry
177
178
    par = start_day.nil? ? [query, params[:service_pack_id]] : [query, params[:service_pack_id], start_day, end_day]
    sql = ActiveRecord::Base.send(:sanitize_sql_array, par)
179
    render json: ActiveRecord::Base.connection.exec_query(sql).to_hash, status: 200
Tam Le's avatar
Tam Le committed
180
181
  end

Khang Le's avatar
Khang Le committed
182
183
184
  private

  def service_pack_params
NguyenHoangTuanKiet's avatar
NguyenHoangTuanKiet committed
185
186
    params.require(:service_pack).permit(:name, :total_units, :started_date, :expired_date, :threshold1, :threshold2, 
      mapping_rates_attributes: [:id, :activity_id, :service_pack_id, :units_per_hour, :_destroy])
Khang Le's avatar
Khang Le committed
187
  end
188

189
end