-
Notifications
You must be signed in to change notification settings - Fork 16
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #296 from DC7806/feature/add_overtimes
加班補休額度申請 (#272)
- Loading branch information
Showing
33 changed files
with
651 additions
and
180 deletions.
There are no files selected for viewing
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
# frozen_string_literal: true | ||
class Backend::OvertimesController < Backend::BaseController | ||
before_action :set_query_object, except: :statistics | ||
|
||
def index | ||
@users = User.all | ||
end | ||
|
||
def verify;end | ||
|
||
def update | ||
if current_object.update(resource_params) | ||
params[:approve] ? approve : reject | ||
else | ||
respond_to do |f| | ||
f.html { render action: :verify } | ||
f.json | ||
end | ||
end | ||
end | ||
|
||
def add_leave_time | ||
@leave_time = LeaveTime.new | ||
end | ||
|
||
def create_leave_time | ||
params[:leave_time][:user_id] = current_object.user.id | ||
@leave_time = LeaveTime.new(resource_params) | ||
if @leave_time.save(resource_params) | ||
action_success(verify_backend_overtime_path(current_object)) | ||
else | ||
render :add_leave_time | ||
end | ||
end | ||
|
||
def add_compensatory_pay | ||
@overtime_pay = OvertimePay.new | ||
end | ||
|
||
def create_compensatory_pay | ||
params[:overtime_pay][:user_id] = current_object.user.id | ||
params[:overtime_pay][:overtime_id] = params[:id] | ||
@overtime_pay = OvertimePay.new(resource_params) | ||
if @overtime_pay.save(resource_params) | ||
action_success(verify_backend_overtime_path(current_object)) | ||
else | ||
render :add_overtime_pay | ||
end | ||
end | ||
|
||
def statistics | ||
search_params = params.fetch(:q, {})&.permit(:year_eq, :month_eq) | ||
@q = Overtime.where(compensatory_type: 'pay', status: :approved).ransack(search_params) | ||
@summary = @q.result | ||
end | ||
|
||
private | ||
|
||
def resource_params | ||
case action_name | ||
when 'create' then params.require(:overtime).permit(:user_id, :hours, :start_time, :end_time, :description) | ||
when 'update' then params.require(:overtime).permit(:comment) | ||
when 'create_leave_time' then params.require(:leave_time).permit(:user_id, :overtime_id, :leave_type, :quota, :effective_date, :expiration_date, :remark) | ||
when 'create_compensatory_pay' then params.require(:overtime_pay).permit(:user_id, :overtime_id, :hour, :remark) | ||
end | ||
end | ||
|
||
def set_query_object | ||
@q = Overtime.ransack(search_params) | ||
end | ||
|
||
def search_params | ||
@search_params = params.fetch(:q, {})&.permit( | ||
:s, :status_eq, :end_time_lteq, :start_time_gteq, :compensatory_type_eq) | ||
end | ||
|
||
def collection_scope | ||
@q.result.preload(:user) | ||
end | ||
|
||
def approve | ||
if current_object.pending? | ||
current_object.approve!(current_user) | ||
action_success | ||
else | ||
action_fail t('warnings.not_verifiable'), :verify | ||
end | ||
end | ||
|
||
def reject | ||
if current_object.pending? or current_object.approved? | ||
current_object.reject!(current_user) | ||
action_success | ||
else | ||
action_fail t('warnings.not_verifiable'), :verify | ||
end | ||
end | ||
end |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
class OvertimesController < BaseController | ||
include Selectable | ||
|
||
def index | ||
@q = current_user.overtimes.order(created_at: :desc).ransack(search_params) | ||
@current_collection = @q.result.page(params[:page]) | ||
@current_collection = Kaminari.paginate_array(@current_collection.first(5)).page(params[:page]) unless params[:q].present? | ||
end | ||
|
||
def new | ||
@current_object = collection_scope.new | ||
end | ||
|
||
def create | ||
@current_object = collection_scope.new(resource_params) | ||
if @current_object.save | ||
action_success | ||
else | ||
render action: :new | ||
end | ||
end | ||
|
||
def update | ||
if current_object.canceled? | ||
action_fail t('warnings.not_cancellable'), :edit | ||
else | ||
current_object.assign_attributes(resource_params) | ||
if !current_object.changed? | ||
action_fail t('warnings.no_change'), :edit | ||
elsif current_object.revise! | ||
action_success | ||
else | ||
render action: :edit | ||
end | ||
end | ||
end | ||
|
||
def cancel | ||
if current_object.may_cancel? | ||
current_object.cancel! | ||
@actions << :cancel | ||
action_success | ||
elsif current_object.approved? | ||
action_fail t('warnings.already_happened'), :index | ||
else | ||
action_fail t('warnings.not_cancellable'), :index | ||
end | ||
end | ||
|
||
private | ||
|
||
def resource_params | ||
params.require(:overtime).permit( | ||
:start_time, :end_time, :description, :compensatory_type | ||
) | ||
end | ||
|
||
def collection_scope | ||
current_user.overtimes | ||
end | ||
|
||
def search_params | ||
@search_params = params.fetch(:q, {})&.permit( | ||
:status_eq, :end_time_lteq, :start_time_gteq, :compensatory_type_eq) | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
# frozen_string_literal: true | ||
module Backend | ||
module OvertimesHelper | ||
def overtime_submit_disabled? | ||
return unless current_object.pay? | ||
!current_object.may_approve? || current_object.overtime_pay&.hour.nil? | ||
end | ||
|
||
def render_append_hours_options | ||
if current_object.may_approve? && current_object.leave? | ||
link_to t("title.backend/overtimes.append_quota"), add_leave_time_backend_overtime_path, class: 'btn btn-warning' | ||
elsif current_object.may_approve? && current_object.pay? | ||
link_to t("title.backend/overtimes.append_overtime_pay"), add_compensatory_pay_backend_overtime_path, class: 'btn btn-warning' | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,61 +1,94 @@ | ||
# frozen_string_literal: true | ||
class Overtime < ApplicationRecord | ||
include AASM | ||
include SignatureConcern | ||
|
||
enum status: Settings.overtimes.statuses | ||
enum compensatory_type: Settings.overtimes.compensatory_types | ||
|
||
belongs_to :user | ||
validates :description, :start_time, :end_time, presence: true | ||
belongs_to :manager, class_name: 'User', foreign_key: 'manager_id' | ||
|
||
has_one :overtime_pay | ||
|
||
validates :description, :start_time, :end_time, :compensatory_type, presence: true | ||
validate :hours_should_be_positive_integer | ||
validate :time_overlapped | ||
|
||
before_validation :assign_hours | ||
enum status: Settings.leave_applications.statuses | ||
|
||
aasm column: :status, enum: true do | ||
state :pending, initial: true | ||
state :approved | ||
state :rejected | ||
state :canceled | ||
|
||
event :approve, after_commit: :create_leave_time do | ||
event :approve, before: proc { |manager| sign(manager) } do | ||
transitions to: :approved, from: :pending | ||
end | ||
|
||
event :reject do | ||
event :reject, before: proc { |manager| sign(manager) } do | ||
transitions to: :rejected, from: %i(pending approved) | ||
end | ||
|
||
event :revise do | ||
transitions to: :pending, from: %i(pending approved) | ||
transitions to: :pending, from: %i(pending) | ||
end | ||
|
||
event :cancel do | ||
transitions to: :canceled, from: :pending | ||
transitions to: :canceled, from: :approved, unless: :happened? | ||
transitions to: :canceled, from: %i(pending approved) | ||
end | ||
end | ||
private | ||
|
||
def happened? | ||
Time.current > self.start_time | ||
def leave_time_params | ||
{ | ||
user_id: self.user_id, | ||
leave_type: 'bonus', | ||
quota: self.hours, | ||
effective_date: self.start_time.to_date, | ||
expiration_date: self.start_time.to_date.end_of_year | ||
} | ||
end | ||
|
||
def auto_calculated_minutes | ||
return @minutes = 0 unless start_time && end_time | ||
@minutes = Daikichi::Config::Biz.within(start_time, end_time).in_minutes | ||
ransacker :year do | ||
Arel.sql('extract(year from created_at)') | ||
end | ||
|
||
ransacker :month do | ||
Arel.sql('extract(month from created_at)') | ||
end | ||
|
||
private | ||
|
||
def assign_hours | ||
self.hours = self.send(:auto_calculated_minutes) / 60 | ||
return unless start_time && end_time | ||
self.hours = ((end_time - start_time) / 3600).to_i | ||
end | ||
|
||
def hours_should_be_positive_integer | ||
return if self.errors[:start_time].any? or self.errors[:end_time].any? | ||
errors.add(:end_time, :not_integer) if (@minutes % 60).nonzero? || !self.hours.positive? | ||
errors.add(:start_time, :should_be_earlier) unless self.end_time > self.start_time | ||
return if errors.any? | ||
errors.add(:end_time, :not_integer) unless ((end_time - start_time).to_i % 3600).zero? | ||
errors.add(:start_time, :should_be_earlier) unless end_time > start_time | ||
end | ||
|
||
def time_overlapped | ||
return if errors.any? | ||
overlapped_records = Overtime.where('(start_time, end_time) OVERLAPS (?, ?)', start_time , end_time).where.not(id: self.id) | ||
return unless overlapped_records.any? | ||
time_overlapped_errors(overlapped_records) | ||
end | ||
|
||
def create_leave_time | ||
if Date.today.month > 10 | ||
LeaveTime.create(leave_type: 'bonus', quota: hours, usable_hours: hours, used_hours: 0, locked_hours: 0, user_id: user_id, effective_date: Date.today, expiration_date: Date.today.end_of_year + 3.months, remark: "申請加班補休核准") | ||
else | ||
LeaveTime.create(leave_type: 'bonus', quota: hours, usable_hours: hours, used_hours: 0, locked_hours: 0, user_id: user_id, effective_date: Date.today, expiration_date: Date.today.end_of_year, remark: "申請加班補休核准") | ||
def time_overlapped_errors(records) | ||
url = Rails.application.routes.url_helpers | ||
records.each do |record| | ||
next if record.rejected? || record.canceled? | ||
errors.add(:base, | ||
I18n.t( | ||
'activerecord.errors.models.overtime.attributes.base.time_range_overlapped', | ||
start_time: record.start_time.to_formatted_s(:month_date), | ||
end_time: record.end_time.to_formatted_s(:month_date), | ||
link: url.overtime_path(id: record.id)) | ||
) | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
class OvertimePay < ApplicationRecord | ||
belongs_to :overtime | ||
belongs_to :user | ||
end |
Oops, something went wrong.