Skip to content

Add the total amount of hours for visible timespan to order_plannings (63115) #232

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 49 additions & 3 deletions app/assets/stylesheets/components/_plannings.scss
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ $cell-width: 36px;
$cell-height: 4rem;
$weekdays: 5;
$week-width: $cell-width * $weekdays;
$legend-width: 420px;
$legend-width: 500px;
$grey: #ddd;
$grey-light: #f3f3f3;

Expand Down Expand Up @@ -151,6 +151,7 @@ body.order_plannings {
.planning-calendar-days,
.planning-calendar-days-header,
.planning-calendar-inner > .groupheader,
.planning-calendar-inner > .tableheader,
.planning-calendar-inner > .actions {
display: flex;
width: calc(var(--days, 1) * #{$cell-width} + #{$legend-width});
Expand All @@ -170,6 +171,7 @@ body.order_plannings {
}
}
.planning-calendar-inner > .groupheader > .legend,
.planning-calendar-inner > .tableheader > .legend,
.planning-calendar-inner > .groupheader > .sticky-wrapper > .legend,
.planning-calendar-inner > .actions > .buttons,
.planning-calendar-inner > .actions > .sticky-wrapper > .buttons,
Expand All @@ -196,9 +198,17 @@ body.order_plannings {
left: $grid-gutter-width;
}

.sum {
.col-sum {
width: 50%;
margin-left: auto;
white-space: nowrap;
justify-content: flex-end;
display: flex;
}

.rowtotals {
margin-left: auto;
display: flex;
width: 0.35*$legend-width;
}
}

Expand Down Expand Up @@ -478,3 +488,39 @@ table.company-planning {
color: #000;
box-shadow: 0 1px 1px rgba(0, 0, 0, 0.1);
}

.header-planned-container {
display: flex;
flex-direction: column;
gap: 8px;
width: fit-content;
}

.header-planned-row {
display: flex;
justify-content: space-between;
align-items: center;
border-bottom: 1px solid #ddd;
padding-bottom: 4px;
}

.header-planned-row:last-child {
border-bottom: none;
}

.header-planned-prefix {
font-weight: bold;
color: #333;
flex: 1;
}

.header-planned-amount {
min-width: 100px;
text-align: right;
font-weight: bold;
}

.header-planned-postfix {
color: #666;
margin-left: 8px;
}
14 changes: 8 additions & 6 deletions app/domain/plannings/order_board.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,9 @@ def row_legend(employee_id, _work_item_id)
employees.detect { |e| e.id == employee_id }
end

def total_row_planned_hours(employee_id, work_item_id)
@total_row_planned_hours ||= load_total_included_rows_planned_hours
def total_row_planned_hours(employee_id, work_item_id, only_for_active_period = false)
period_to_calculate_hours = only_for_active_period ? @period : Period.new(nil, nil)
@total_row_planned_hours = load_total_included_rows_planned_hours(period_to_calculate_hours)
@total_row_planned_hours[key(employee_id, work_item_id)] || 0
end

Expand All @@ -28,8 +29,9 @@ def total_plannable_hours
end

# total planned hours on this order for all times, not limited to current period.
def total_planned_hours
WorkingCondition.sum_with(:must_hours_per_day, Period.new(nil, nil)) do |period, val|
def total_planned_hours(only_for_active_period = false)
period_to_calculate_hours = only_for_active_period ? @period : Period.new(nil, nil)
WorkingCondition.sum_with(:must_hours_per_day, period_to_calculate_hours) do |period, val|
percent_to_hours(load_plannings(period).sum(:percent), val)
end
end
Expand Down Expand Up @@ -63,9 +65,9 @@ def load_accounting_posts
.list
end

def load_total_included_rows_planned_hours
def load_total_included_rows_planned_hours(row_period = Period.new(nil, nil))
hours = {}
WorkingCondition.each_period_of(:must_hours_per_day, Period.new(nil, nil)) do |period, val|
WorkingCondition.each_period_of(:must_hours_per_day, row_period) do |period, val|
load_plannings(period)
.where(included_plannings_condition)
.group(:employee_id, :work_item_id)
Expand Down
1 change: 1 addition & 0 deletions app/views/order_plannings/_header.html.haml
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@
.planned{ id: "planned_#{dom_id(@board.subject)}" }
= render 'header_planned'
= render 'date_filter' if filter
%br
19 changes: 15 additions & 4 deletions app/views/plannings/base/_header_planned.html.haml
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,19 @@
-# or later. See the COPYING file at the top-level directory or at
-# https://github.com/puzzle/puzzletime.

.header-planned-container
.header-planned-row.total-sum
.header-planned-prefix
Total:
.header-planned-amount
= format_number(@board.total_planned_hours, 0) + ' / ' + format_number(@board.total_plannable_hours, 0)
.header-planned-postfix
Stunden verplant
.header-planned-row.inperiod-sum
.header-planned-prefix
Ausgewählter Zeitbereich:
.header-planned-amount
= format_number(@board.total_planned_hours(true), 0)
.header-planned-postfix
Stunden verplant

= format_number(@board.total_planned_hours, 0)
von
= format_number(@board.total_plannable_hours, 0)
Stunden verplant
17 changes: 12 additions & 5 deletions app/views/plannings/base/_row.html.haml
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,18 @@
.legend{ title: legend }
= link_to_if(can?(:show_plannings, legend), legend, planning_legend_path(legend))

.sum
- row_total_overall = true if local_assigns[:row_total_overall].nil?
- total_tooltip = row_total_overall ? 'Total der auf dieser Position geplanten Zeit' : 'Total der auf dieser Position geplanten Zeit im dargestellten Zeitbereich'
= with_tooltip(total_tooltip) do
= format_hour(row_total, 0)
.rowtotals
- total_period_tooltip = 'Total der auf dieser Position geplanten Zeit im dargestellten Zeitbereich'
- total_position_tooltip = 'Total der auf dieser Position geplanten Zeit'
.col-sum.inperiod-sum
- if !local_assigns[:row_total_period].nil?
= with_tooltip(total_period_tooltip) do
= format_hour(row_total_period, 0)
.col-sum.total-sum
- row_total_overall = true if local_assigns[:row_total_overall].nil?
- total_tooltip = row_total_overall ? total_position_tooltip : total_period_tooltip
= with_tooltip(total_tooltip) do
= format_hour(row_total, 0)

- items.each do |item|
.day{ item.day_attrs }
Expand Down
14 changes: 14 additions & 0 deletions app/views/plannings/orders/_board.html.haml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,19 @@
= link_to('Auftrag', order_accounting_posts_path(@board.subject))

= render 'board_header'
.tableheader
.legend
%small
Member
.rowtotals
.col-sum
%small
In Zeitbereich
.col-sum
%small
Total
- @board.work_days.times do
.day

- @board.accounting_posts.each do |post|
- if post.work_item_id != @board.order.work_item_id
Expand All @@ -34,6 +47,7 @@
legend: employee,
items: items,
row_total: @board.total_row_planned_hours(employee.id, post.work_item_id),
row_total_period: @board.total_row_planned_hours(employee.id, post.work_item_id, only_for_active_period=true),
row_total_overall: true

- if can?(:manage_plannings, @board.subject)
Expand Down
22 changes: 22 additions & 0 deletions test/domain/plannings/order_board_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,18 @@ class OrderBoardTest < ActiveSupport::TestCase
assert_equal 16, board.total_row_planned_hours(employees(:lucien).id, work_items(:hitobito_demo_app).id)
end

test '#total_row_planned_hours includes plannings from only the active period if the respective flag is set' do
create_plannings
Planning.create!(work_item_id: work_items(:hitobito_demo_app).id,
employee_id: employees(:lucien).id,
date: date - 28.days,
percent: 100)

board = Plannings::OrderBoard.new(order, period)

assert_equal 8, board.total_row_planned_hours(employees(:lucien).id, work_items(:hitobito_demo_app).id, true)
end

test '#total_post_planned_hours includes plannings for all employees, even if only some are included' do
create_plannings
board = Plannings::OrderBoard.new(order, period)
Expand Down Expand Up @@ -144,6 +156,16 @@ class OrderBoardTest < ActiveSupport::TestCase
assert_equal 24, board.total_planned_hours
end

test '#total_planned_hours are calculated for entire timespan or only the active period, depending on the passed flag' do
create_plannings

board = Plannings::OrderBoard.new(order, period)
board.for_rows([[employees(:lucien).id, work_items(:hitobito_demo_app).id]])

assert_equal 24, board.total_planned_hours(false)
assert_equal 20, board.total_planned_hours(true)
end

private

def period
Expand Down
70 changes: 62 additions & 8 deletions test/integration/plannings_orders_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -112,8 +112,8 @@ class PlanningsOrdersTest < ActionDispatch::IntegrationTest
end

test 'create planning entries' do
page.assert_selector("#planned_order_#{orders(:puzzletime).id}",
text: '6 von 100 Stunden verplant')
page.assert_selector("#planned_order_#{orders(:puzzletime).id} .total-sum .header-planned-amount",
text: '6 / 100')
drag(row_pascal.all('.day')[2], row_pascal.all('.day')[4])

page.assert_selector('.-selected', count: 3)
Expand All @@ -130,8 +130,8 @@ class PlanningsOrdersTest < ActionDispatch::IntegrationTest
page.assert_selector('.planning-panel', visible: false)
assert_percents ['50', '', '', '', '', ''], row_mark
assert_percents ['25', '', '100', '100', '100', ''], row_pascal
page.assert_selector("#planned_order_#{orders(:puzzletime).id}",
text: '30 von 100 Stunden verplant')
page.assert_selector("#planned_order_#{orders(:puzzletime).id} .total-sum .header-planned-amount",
text: '30 / 100')
end

test 'create planning entries with multiple accounting posts' do
Expand All @@ -140,8 +140,8 @@ class PlanningsOrdersTest < ActionDispatch::IntegrationTest

visit plannings_order_path(orders(:hitobito_demo))

page.assert_selector("#planned_order_#{orders(:hitobito_demo).id}",
text: '16 von 0 Stunden verplant')
page.assert_selector("#planned_order_#{orders(:hitobito_demo).id} .total-sum .header-planned-amount",
text: '16 / 0')
page.assert_selector("#group_header_times_accounting_post_#{accounting_posts(:hitobito_demo_app).id}",
text: '10 / 0 h')
page.assert_selector("#group_header_times_accounting_post_#{accounting_posts(:hitobito_demo_site).id}",
Expand All @@ -157,8 +157,8 @@ class PlanningsOrdersTest < ActionDispatch::IntegrationTest
click_button 'OK'
end

page.assert_selector("#planned_order_#{orders(:hitobito_demo).id}",
text: '40 von 0 Stunden verplant')
page.assert_selector("#planned_order_#{orders(:hitobito_demo).id} .total-sum .header-planned-amount",
text: '40 / 0')
page.assert_selector("#group_header_times_accounting_post_#{accounting_posts(:hitobito_demo_app).id}",
text: '34 / 0 h')
page.assert_selector("#group_header_times_accounting_post_#{accounting_posts(:hitobito_demo_site).id}",
Expand Down Expand Up @@ -538,6 +538,60 @@ class PlanningsOrdersTest < ActionDispatch::IntegrationTest
page.assert_selector('.selectize-dropdown-content', count: 1)
end

test 'total time and visible time are shown per row' do
date = Time.zone.today.beginning_of_week
Planning.create!({ employee_id: employees(:mark).id,
work_item_id:,
date: (date + 1.day).strftime('%Y-%m-%d'),
percent: 50,
definitive: true })
Planning.create!({ employee_id: employees(:mark).id,
work_item_id:,
date: (date + 4.months).strftime('%Y-%m-%d'),
percent: 50,
definitive: true })

visit plannings_order_path(orders(:puzzletime))

assert_equal '8 h', row_mark.find('.inperiod-sum').text
assert_equal '12 h', row_mark.find('.total-sum').text

select 'Nächste 12 Monate', from: 'period_shortcut'
sleep 0.5 # give time to update values

assert_equal '12 h', row_mark.find('.inperiod-sum').text
assert_equal '12 h', row_mark.find('.total-sum').text
end

test 'total overall time for selected period is shown' do
date = Time.zone.today.beginning_of_week
Planning.create!({ employee_id: employees(:mark).id,
work_item_id:,
date: (date + 1.day).strftime('%Y-%m-%d'),
percent: 50,
definitive: true })
Planning.create!({ employee_id: employees(:mark).id,
work_item_id:,
date: (date + 4.months).strftime('%Y-%m-%d'),
percent: 50,
definitive: true })

visit plannings_order_path(orders(:puzzletime))

page.assert_selector("#planned_order_#{orders(:puzzletime).id} .total-sum .header-planned-amount",
text: '14 / 100')
page.assert_selector("#planned_order_#{orders(:puzzletime).id} .inperiod-sum .header-planned-amount",
text: '10')

select 'Nächste 12 Monate', from: 'period_shortcut'
sleep 0.5 # give time to update values

page.assert_selector("#planned_order_#{orders(:puzzletime).id} .total-sum .header-planned-amount",
text: '14 / 100')
page.assert_selector("#planned_order_#{orders(:puzzletime).id} .inperiod-sum .header-planned-amount",
text: '14')
end

private

def workdays_next_n_months(n, date = Time.zone.today)
Expand Down