Skip to content

Commit

Permalink
Merge pull request #51 from dhanasingh/dev
Browse files Browse the repository at this point in the history
v2.1.2 changes
  • Loading branch information
suganya-thulasiraman committed Mar 28, 2016
2 parents 6543479 + 46ad2cc commit fae5c3e
Show file tree
Hide file tree
Showing 32 changed files with 790 additions and 408 deletions.
30 changes: 12 additions & 18 deletions README.rdoc
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
= wktime
= Time & Attendance
This Plugin provides the capability to submit Time, Expense and Attendance within redmine. The user must be a
member of a project with permission to log time. If the user has 'Edit time logs' permission,
then he can manage other team member's Time & Expense as well.

This plugin uses the existing Time Entry model for Time sheets and has its own model called
Wk Expense Entry for Expense Sheets. New Time & Expense sheets can be entered using the link
‘New sheet’, new issues can be added to the Sheets using the ‘Add Row’ link. Users without
Edit permissions cannot edit/delete time & expense entries.
This plugin uses the existing Time Entry model for Time sheets and has its own Wk Expense Entry model
for Expense Sheets and Wk Attendance model for attendances. New Time & Expense sheets can be entered using the link ‘New sheet’,
new issues can be added to the Sheets using the ‘Add Row’ link. Users without Edit permissions cannot edit/delete time & expense entries.
The time & expense sheets can be exported into pdf and csv format.

The following configurations can be made on the plugin
Expand All @@ -33,7 +32,7 @@ The following configurations can be made on the plugin
- T&E Admin groups can be configured
- Enable Clock In / Clock Out
- Break time and Leaves can be configured
- Join date, Date of birth, Designation, Employee Id can be configured
- Join date, Date of birth, Designation, Employee Id, Termination date can be configured

The Time & Expense sheets can be approved/rejected by supervisors after it is submitted by Project Members.
Here is the workflow of Approval system..
Expand Down Expand Up @@ -78,19 +77,14 @@ If an apache passenger module is used then make sure the following settings are
b) RailsAppSpawnerIdleTime 0
c) PassengerPreStart http://rails-app-url/

Release Notes for 2.1
The plugin name is renamed to Time & Attendance.

Release Notes for 2.1.2
Features:
- Made compatible with Redmine 3.2.0.
- Attendance module is introduced.
- German translation is included.
Bugs:
- Fixed SQL Server issue.
- Fixed time entering format issue.
- Fixed issue forbidden error on "Enter issue as ID/Subject".

We would like to thank Luna Lenardi for contributing towards German Translation and for fixing a currency issue.
- Made compatible with Redmine 3.2.1.
- User filter introduced in Attendance tab.
- Previous and Next link added in attendance detail page.
- Group filter introduced in Reports tab.
Bugs:
- Fixed decimals not taken into account when registering expenses.

Customization:
For any Customization/Support, please contact us, our consulting team will be happy to help you
Expand Down
172 changes: 49 additions & 123 deletions app/controllers/wkattendance_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,22 +8,34 @@ class WkattendanceController < ApplicationController
before_filter :check_perm_and_redirect, :only => [:edit, :update]

def index
@status = params[:status] || 1
@groups = Group.all.sort
sqlStr = ""
lastMonthStartDt = Date.civil(Date.today.year, Date.today.month, 1) << 1
if(Setting.plugin_redmine_wktime['wktime_leave'].blank?)
sqlStr = " select u.id as user_id, -1 as issue_id from users u where u.type = 'User' "
sqlStr = " select u.id as user_id, u.firstname, u.lastname, u.status, -1 as issue_id from users u where u.type = 'User' "
else
listboxArr = Setting.plugin_redmine_wktime['wktime_leave'][0].split('|')
issueId = listboxArr[0]
sqlStr = getQueryStr + " where i.id in (#{issueId}) and u.type = 'User'"
sqlStr = getListQueryStr + " where u.type = 'User' and (cvt.value is null or #{getConvertDateStr('cvt.value')} >= '#{lastMonthStartDt}')"
end
if !isAccountUser
sqlStr = sqlStr + " and u.id = #{User.current.id} "
end
end
if !@status.blank?
sqlStr = sqlStr + " and u.status = #{@status}"
end
if !params[:group_id].blank?
sqlStr = sqlStr + " and gu.group_id = #{params[:group_id]}"
end
if !params[:name].blank?
sqlStr = sqlStr + " and (LOWER(u.firstname) like LOWER('%#{params[:name]}%') or LOWER(u.lastname) like LOWER('%#{params[:name]}%'))"
end
findBySql(sqlStr)
end

def edit
sqlStr = getQueryStr + " where i.id in (#{getLeaveIssueIds}) and u.type = 'User' and u.id = #{params[:user_id]}"
sqlStr = getQueryStr + " where i.id in (#{getLeaveIssueIds}) and u.type = 'User' and u.id = #{params[:user_id]} order by i.subject"
@leave_details = WkUserLeave.find_by_sql(sqlStr)
render :action => 'edit'
end
Expand All @@ -32,6 +44,7 @@ def update
errorMsg =nil
wkuserleave = nil
ids = params[:ids]
accrualOn = params[:accrual_on]
newIssueIds = params[:new_issue_ids]
newIssueArr = newIssueIds.split(',')
userId = params[:user_id]
Expand All @@ -57,7 +70,7 @@ def update
wkuserleave.balance = params["balance_"+issueId]
wkuserleave.accrual = params["accrual_"+issueId]
wkuserleave.used = params["used_"+issueId]
wkuserleave.accrual_on = Date.civil(Date.today.year, Date.today.month, 1) -1
wkuserleave.accrual_on = accrualOn #Date.civil(Date.today.year, Date.today.month, 1) -1
if !wkuserleave.save()
errorMsg = wkuserleave.errors.full_messages.join('\n')
end
Expand All @@ -72,131 +85,36 @@ def update
end
end

def getLeaveIssueIds
issueIds = ''
if(Setting.plugin_redmine_wktime['wktime_leave'].blank?)
issueIds = '-1'
else
Setting.plugin_redmine_wktime['wktime_leave'].each do |element|
if issueIds!=''
issueIds = issueIds +','
end
listboxArr = element.split('|')
issueIds = issueIds + listboxArr[0]
end
end
issueIds
end

def getReportLeaveIssueIds
issueIds = ''
if(Setting.plugin_redmine_wktime['wktime_leave'].blank?)
issueIds = '-1'
else
Setting.plugin_redmine_wktime['wktime_leave'].each_with_index do |element,index|
if index < 3
if issueIds!=''
issueIds = issueIds +','
end
listboxArr = element.split('|')
issueIds = issueIds + listboxArr[0]
end
end
end
issueIds
end

def getQueryStr
queryStr = ''
queryStr = "select u.id as user_id, i.id as issue_id,w.balance, w.accrual, w.used, w.accrual_on, w.id from users u
cross join issues i left join (SELECT wl.* FROM wk_user_leaves wl inner join"
queryStr = queryStr + " ( select max(accrual_on) as accrual_on, user_id, issue_id from wk_user_leaves
group by user_id, issue_id) t"
queryStr = queryStr + " on wl.user_id = t.user_id and wl.issue_id = t.issue_id
and wl.accrual_on = t.accrual_on) w on w.user_id = u.id and w.issue_id = i.id"
accrualOn = params[:accrual_on].blank? ? Date.civil(Date.today.year, Date.today.month, 1) -1 : params[:accrual_on].to_s.to_date
queryStr = "select u.id as user_id, u.firstname, u.lastname, i.id as issue_id,w.balance, w.accrual, w.used, w.accrual_on, w.id from users u " +
"left join custom_values cvt on (u.id = cvt.customized_id and cvt.value != '' and cvt.custom_field_id = #{getSettingCfId('wktime_attn_terminate_date_cf')} ) " +
"cross join issues i left join wk_user_leaves w on w.user_id = u.id and w.issue_id = i.id
and w.accrual_on = '#{accrualOn}' "
queryStr
end

def report
retrieve_date_range
if params[:report_type] == 'attendance_report'
reportattn
end
end

def reportattn
dateStr = getConvertDateStr('start_time')
sqlStr = ""
if isAccountUser
@userlist = User.where("type = ?", 'User').order('id')
leave_data = WkUserLeave.where("issue_id in (#{getReportLeaveIssueIds}) and accrual_on between '#{@from}' and '#{@to}'")
leave_entry = TimeEntry.where("issue_id in (#{getLeaveIssueIds}) and spent_on between '#{@from}' and '#{@to}'")
sqlStr = "select user_id,#{dateStr} as spent_on,sum(hours) as hours from wk_attendances where start_time between '#{@from}' and '#{@to}' group by user_id,#{dateStr}"
else
@userlist = User.where("type = ? AND id = ?", 'User', User.current.id)
leave_data = WkUserLeave.where("issue_id in (#{getReportLeaveIssueIds}) and accrual_on between '#{@from}' and '#{@to}' and user_id = #{User.current.id} " )
leave_entry = TimeEntry.where("issue_id in (#{getLeaveIssueIds}) and spent_on between '#{@from}' and '#{@to}' and user_id = #{User.current.id} " )
sqlStr = "select user_id,#{dateStr} as spent_on,sum(hours) as hours from wk_attendances where start_time between '#{@from}' and '#{@to}' and user_id = #{User.current.id} group by user_id,#{dateStr}"
end
daily_entries = WkAttendance.find_by_sql(sqlStr)
@attendance_entries = Hash.new
if !leave_data.blank?
leave_data.each_with_index do |entry,index|
@attendance_entries[entry.user_id.to_s + '_' + entry.issue_id.to_s + '_balance'] = entry.balance
@attendance_entries[entry.user_id.to_s + '_' + entry.issue_id.to_s + '_used'] = entry.used
@attendance_entries[entry.user_id.to_s + '_' + entry.issue_id.to_s + '_accrual'] = entry.accrual
end
end
if !leave_entry.blank?
leave_entry.each_with_index do |entry,index|
@attendance_entries[entry.user_id.to_s + '_' + entry.spent_on.to_date.strftime("%d").to_i.to_s + '_leave'] = entry.issue_id
def getListQueryStr
accrualOn = params[:accrual_on].blank? ? Date.civil(Date.today.year, Date.today.month, 1) -1 : params[:accrual_on].to_s.to_date
selectColStr = "select u.id as user_id, u.firstname, u.lastname, u.status"
joinTableStr = ""
Setting.plugin_redmine_wktime['wktime_leave'].each_with_index do |element,index|
if index < 5
tAlias = "w#{index.to_s}"
listboxArr = element.split('|')
joinTableStr = joinTableStr + " left join wk_user_leaves #{tAlias} on #{tAlias}.user_id = u.id and #{tAlias}.issue_id = " + listboxArr[0] + " and #{tAlias}.accrual_on = '#{accrualOn}'"
selectColStr = selectColStr + ", (#{tAlias}.balance + #{tAlias}.accrual - #{tAlias}.used) as total#{index.to_s}"
end
end
if !daily_entries.blank?
daily_entries.each_with_index do |entry,index|
@attendance_entries[entry.user_id.to_s + '_' + entry.spent_on.to_date.strftime("%d").to_i.to_s + '_hours'] = entry.hours
end
queryStr = selectColStr + " from users u left join custom_values cvt on (u.id = cvt.customized_id and cvt.value != '' and cvt.custom_field_id = #{getSettingCfId('wktime_attn_terminate_date_cf')} ) " + joinTableStr

if !params[:group_id].blank?
queryStr = queryStr + " left join groups_users gu on u.id = gu.user_id"
end
render :action => 'reportattn'
queryStr
end

# Retrieves the date range based on predefined ranges or specific from/to param dates
def retrieve_date_range
@free_period = false
@from, @to = nil, nil
period_type = params[:period_type]
period = params[:period]
fromdate = params[:from]
todate = params[:to]

if (period_type == '1' || (period_type.nil? && !period.nil?))
case period.to_s
when 'current_month'
@from = Date.civil(Date.today.year, Date.today.month, 1)
@to = (@from >> 1) - 1
when 'last_month'
@from = Date.civil(Date.today.year, Date.today.month, 1) << 1
@to = (@from >> 1) - 1
end
elsif period_type == '2' || (period_type.nil? && (!fromdate.nil? || !todate.nil?))
begin; @from = Date.civil((fromdate.to_s.to_date).year,(fromdate.to_s.to_date).month, 1) unless fromdate.blank?; rescue; end
begin; @to = (@from >> 1) - 1 unless @from.blank?; rescue; end
if @from.blank?
@from = Date.civil(Date.today.year, Date.today.month, 1)
@to = (@from >> 1) - 1
end
@free_period = true
else
# default
# 'current_month'
@from = Date.civil(Date.today.year, Date.today.month, 1)
@to = (@from >> 1) - 1
end

@from, @to = @to, @from if @from && @to && @from > @to

end

def getIssuesByProject
issue_by_project=""
issueList=[]
Expand All @@ -212,10 +130,16 @@ def getIssuesByProject
def getPrjIssues
issueList = []
project_id = 0
project = nil
if !params[:project_id].blank?
project_id = params[:project_id]
project = Project.find(project_id)
end
if ((!project.blank? && (project.status == Project::STATUS_CLOSED || project.status == Project::STATUS_ARCHIVED)) && !params[:issue_id].blank?)
issueList = Issue.where(:id => params[:issue_id], :project_id => project_id)
else
issueList = Issue.where(:project_id => project_id)
end
issueList = Issue.where(:project_id => project_id)
issueList
end

Expand All @@ -234,15 +158,17 @@ def check_permission

def getProjectByIssue
project_id=""
project_by_issue=""
if !params[:issue_id].blank?
issue_id = params[:issue_id]
issues = Issue.where(:id => issue_id.to_i)
project_id = issues[0].project_id
project_by_issue = issues[0].project_id.to_s + '|' + issues[0].project.name
end
respond_to do |format|
format.text { render :text => project_id }
format.text { render :text => project_by_issue }
end
end
end

def setLimitAndOffset
if api_request?
Expand Down
Loading

0 comments on commit fae5c3e

Please sign in to comment.