Skip to content

Commit

Permalink
fix: fixed team hour value realized chart logic
Browse files Browse the repository at this point in the history
  • Loading branch information
celsoMartins committed Dec 6, 2023
1 parent aca5395 commit 1e82309
Show file tree
Hide file tree
Showing 25 changed files with 490 additions and 224 deletions.
1 change: 0 additions & 1 deletion app/controllers/demand_blocks_controller.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
# frozen_string_literal: true

class DemandBlocksController < AuthenticatedController
before_action :user_gold_check
before_action :assign_project, except: %i[index demand_blocks_csv search]
before_action :assign_demand, except: %i[index demand_blocks_csv search]
before_action :assign_demand_block, except: %i[index demand_blocks_csv search]
Expand Down
7 changes: 0 additions & 7 deletions app/graphql/types/team_member_consolidation_list_type.rb

This file was deleted.

9 changes: 0 additions & 9 deletions app/graphql/types/team_member_consolidation_type.rb

This file was deleted.

7 changes: 0 additions & 7 deletions app/graphql/types/team_members_hourly_rate_list_type.rb

This file was deleted.

8 changes: 0 additions & 8 deletions app/graphql/types/team_members_hourly_rate_type.rb

This file was deleted.

2 changes: 2 additions & 0 deletions app/graphql/types/teams/member_efficiency_data_type.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ class MemberEfficiencyDataType < Types::BaseObject
field :avg_hours_per_demand, Float
field :cards_count, Int
field :effort_in_month, Float
field :hour_value_expected, Float
field :hour_value_realized, Float
field :member_capacity_value, Int
field :membership, Types::Teams::MembershipType
field :realized_money_in_month, Float
Expand Down
1 change: 1 addition & 0 deletions app/graphql/types/teams/member_efficiency_list_type.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ module Teams
class MemberEfficiencyListType < Types::BaseObject
field :avg_hours_per_member, Float, null: false
field :avg_money_per_member, Float, null: false
field :date, GraphQL::Types::ISO8601Date, null: false
field :members_efficiency, [Types::Teams::MemberEfficiencyDataType], null: false
field :team_capacity_hours, Integer, null: false
field :total_hours_produced, Float, null: false
Expand Down
11 changes: 11 additions & 0 deletions app/graphql/types/teams/membership_hour_value_chart_data_type.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# frozen_string_literal: true

module Types
module Teams
class MembershipHourValueChartDataType < Types::BaseObject
field :date, GraphQL::Types::ISO8601Date
field :hour_value_expected, Float
field :hour_value_realized, Float
end
end
end
10 changes: 10 additions & 0 deletions app/graphql/types/teams/membership_hour_value_chart_list_type.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# frozen_string_literal: true

module Types
module Teams
class MembershipHourValueChartListType < Types::BaseObject
field :membership, Types::Teams::MembershipType
field :membership_hour_value_chart_data, [Types::Teams::MembershipHourValueChartDataType]
end
end
end
23 changes: 0 additions & 23 deletions app/graphql/types/teams/membership_type.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,34 +16,11 @@ class MembershipType < Types::BaseObject
field :team_id, Integer, null: false
field :team_member_id, Integer, null: false
field :team_member_name, String, null: false
field :team_members_hourly_rate_list, [Types::TeamMembersHourlyRateType], null: true
field :updated_at, GraphQL::Types::ISO8601DateTime, null: false

def member_role_description
I18n.t("activerecord.attributes.membership.enums.member_role.#{object.member_role}")
end

# TODO: fix logic
def team_members_hourly_rate_list
return unless object.monthly_payment != 0 && object.team_member.billable?

hourly_rate = []
(1..7).reverse_each { |date| hourly_rate << build_hour_rate(date) }
hourly_rate
end

private

def build_hour_rate(date)
{ 'hour_value_realized' => compute_hours_per_month(object.monthly_payment, object.effort_in_period(Time.zone.today.ago(date.month).beginning_of_month, Time.zone.today.ago(date.month).end_of_month)), 'period_date' => Time.zone.today.ago(date.month).end_of_month }
end

def compute_hours_per_month(monthly_payment, effort_in_period)
return monthly_payment if effort_in_period.zero?

result = monthly_payment / effort_in_period
result.round(2)
end
end
end
end
25 changes: 7 additions & 18 deletions app/graphql/types/teams/team_member_type.rb
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,6 @@ class TeamMemberType < Types::BaseObject
argument :sort_direction, Types::Enums::SortDirection, required: false
end

field :team_member_consolidation_list, [Types::TeamMemberConsolidationType], null: true

field :average_pull_interval_data, Types::Charts::SimpleDateChartDataType, null: true
field :lead_time_control_chart_data, Types::Charts::ControlChartType, null: true
field :lead_time_histogram_chart_data, Types::Charts::LeadTimeHistogramDataType, null: true
Expand Down Expand Up @@ -85,15 +83,6 @@ def demands(status: 'ALL', type: 'ALL', limit: nil)
demands.limit(limit)
end

# TODO: Fix logic
def team_member_consolidation_list
membership = object
members_value_per_hour = []
(1..13).reverse_each { |month| members_value_per_hour << build_member_value_per_hour(month, membership) }

members_value_per_hour
end

def demand_efforts_list(from_date: nil, until_date: nil, page_number: nil)
efforts = object.demand_efforts.to_dates(from_date, until_date).order(start_time_to_computation: :desc)
efforts_paginated = efforts.page(page_number).per(10)
Expand Down Expand Up @@ -177,20 +166,20 @@ def project_hours_data

private

# TODO: Fix Logic
def build_member_value_per_hour(month, membership)
{ 'consolidation_date' => month.month.ago.beginning_of_month, 'hour_value_realized' => compute_hours_per_month(membership.monthly_payment, membership.demand_efforts.to_dates(month.month.ago.beginning_of_month, month.month.ago.end_of_month).sum(&:effort_value).to_f) }
end

def operations_dashboards
@operations_dashboards ||= Dashboards::OperationsDashboard.where(
team_member: object,
last_data_in_month: true
).where('operations_dashboards.dashboard_date > :limit_date', limit_date: 6.months.ago.beginning_of_day).order(:dashboard_date)
end

def member_effort_data_interval = 6.months.ago.at_beginning_of_month.beginning_of_day
def member_effort_daily_interval = 30.days.ago.beginning_of_day
def member_effort_data_interval
6.months.ago.at_beginning_of_month.beginning_of_day
end

def member_effort_daily_interval
30.days.ago.beginning_of_day
end

def first_day_of_six_months_hash
accumulator = Hash.new { |hash, key| hash[key] = 0 }
Expand Down
29 changes: 21 additions & 8 deletions app/graphql/types/teams/team_type.rb
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,13 @@ class TeamType < Types::BaseObject
field :lead_time_p80, Float, null: true
field :lead_time_p95, Float, null: true
field :max_work_in_progress, Int, null: false
field :membership_hour_value_chart_list_type, [Types::Teams::MembershipHourValueChartListType] do
argument :end_date, GraphQL::Types::ISO8601Date, required: false
argument :start_date, GraphQL::Types::ISO8601Date, required: false
end
field :memberships, [Types::Teams::MembershipType] do
argument :active, Boolean, required: false
end

field :name, String, null: false
field :number_of_demands_delivered, Int, null: true
field :projects, [Types::ProjectType], null: true
Expand All @@ -59,8 +62,6 @@ class TeamType < Types::BaseObject
field :throughput_data, [Int], null: true
field :work_in_progress, Int, null: true

field :team_members_hourly_rate_list, [Types::TeamMembersHourlyRateType], null: true

delegate :projects, to: :object

def latest_deliveries(order_field: 'end_date', sort_direction: :desc, limit: 5, start_date: '')
Expand Down Expand Up @@ -144,7 +145,7 @@ def team_consolidations_weekly(start_date: 6.months.ago, end_date: Time.zone.tod
weekly_team_consolidations = object.team_consolidations.weekly_data.order(:consolidation_date)

consolidations = Consolidations::TeamConsolidation
.where(id: weekly_team_consolidations.map(&:id) + [last_consolidation&.id])
.where(id: weekly_team_consolidations.map(&:id) + [last_consolidation&.id])
consolidations = consolidations.where('consolidation_date >= :limit_date', limit_date: start_date) if start_date.present?
consolidations = consolidations.where('consolidation_date <= :limit_date', limit_date: end_date) if end_date.present?
consolidations.order(:consolidation_date)
Expand All @@ -159,10 +160,7 @@ def team_monthly_investment(start_date: 6.months.ago, end_date: Time.zone.today)
array_of_months.each do |date|
total_cost_per_week.append(object.realized_money_in_month(date).round(2) - object.monthly_investment(date).round(2))
end
{
x_axis: array_of_months,
y_axis: total_cost_per_week
}
{ x_axis: array_of_months, y_axis: total_cost_per_week }
end

def team_member_efficiency(month: Time.zone.today.month, year: Time.zone.today.year)
Expand All @@ -172,6 +170,21 @@ def team_member_efficiency(month: Time.zone.today.month, year: Time.zone.today.y
TeamService.instance.compute_memberships_realized_hours(object, start_date, end_date)
end

def membership_hour_value_chart_list_type(start_date: 6.months.ago, end_date: Time.zone.now)
months = TimeService.instance.months_between_of(start_date, end_date)

memberships_hour_value_list = []
object.memberships.active.billable_member.each do |membership|
membership_hour_value_chart_data = []
months.each do |month|
membership_hour_value_chart_data.push({ date: month, hour_value_expected: membership.expected_hour_value(month), hour_value_realized: membership.realized_hour_value(month) })
end
memberships_hour_value_list.push({ membership: membership, membership_hour_value_chart_data: membership_hour_value_chart_data })
end

memberships_hour_value_list
end

def memberships(active: nil)
membership = object.memberships
membership = active ? membership.active : membership.inactive
Expand Down
10 changes: 9 additions & 1 deletion app/models/membership.rb
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ class Membership < ApplicationRecord
has_many :membership_available_hours_histories, class_name: 'History::MembershipAvailableHoursHistory', dependent: :destroy

validates :start_date, :member_role, presence: true
validate :active_team_member_unique

scope :active, -> { where('memberships.end_date' => nil) }
scope :inactive, -> { where.not('memberships.end_date' => nil) }
Expand All @@ -48,7 +49,6 @@ class Membership < ApplicationRecord
delegate :company, to: :team
delegate :projects, to: :team_member

before_create :active_team_member_unique
before_update :save_hours_history

def to_hash
Expand Down Expand Up @@ -109,6 +109,14 @@ def expected_hour_value(date = Time.zone.now)
monthly_payment(date) / current_hours_per_month
end

def realized_hour_value(date = Time.zone.now)
realized_effort = effort_in_period(date.beginning_of_month, date.end_of_month)

return 0 if realized_effort.zero?

monthly_payment(date) / realized_effort
end

def monthly_payment(date = Time.zone.now)
return 0 if team_member.monthly_payment.blank?

Expand Down
6 changes: 3 additions & 3 deletions app/services/slack/slack_notification_service.rb
Original file line number Diff line number Diff line change
Expand Up @@ -251,10 +251,10 @@ def notify_item_blocked(demand_block, demand_url, edit_block_url, block_state =
end

def notify_team_efficiency(slack_notifier, team, start_date, end_date, title, notification_period)
average_team_efficiency = TeamService.instance.compute_memberships_realized_hours(team, start_date, end_date)
return if average_team_efficiency.blank?
efficiency_data = TeamService.instance.compute_memberships_realized_hours(team, start_date, end_date)
return if efficiency_data.blank?

members_efforts = average_team_efficiency[:members_efficiency].reject { |member_effort| member_effort.try(:[], :membership).try(:[], :hours_per_month).blank? && member_effort.try(:[], :membership).try(:[], :hours_per_month)&.zero? }
members_efforts = efficiency_data[:members_efficiency].reject { |member_effort| member_effort.try(:[], :membership).try(:[], :hours_per_month).blank? && member_effort.try(:[], :membership).try(:[], :hours_per_month)&.zero? }

return if members_efforts.blank?

Expand Down
12 changes: 4 additions & 8 deletions app/services/team_service.rb
Original file line number Diff line number Diff line change
Expand Up @@ -70,23 +70,19 @@ def compute_memberships_realized_hours(team, start_date, end_date)
{ membership: membership, effort_in_month: membership.effort_in_period(start_date, end_date).to_f,
avg_hours_per_demand: membership.avg_hours_per_demand(start_date, end_date).to_f,
cards_count: membership.cards_count(start_date, end_date),
realized_money_in_month: membership.realized_money_in_period(start_date, end_date).to_f, member_capacity_value: membership.current_hours_per_month(end_date) || 0,
hour_value_realized: compute_hour_value(membership.monthly_payment(end_date), membership.effort_in_period(start_date, end_date)).to_f,
realized_money_in_month: membership.realized_money_in_period(start_date, end_date).to_f,
member_capacity_value: membership.current_hours_per_month(end_date) || 0,
hour_value_realized: membership.realized_hour_value(end_date).to_f,
hour_value_expected: membership.expected_hour_value(end_date).to_f }
end

efficiency_data = efficiency_data.sort_by { |member_efficiency| member_efficiency[:effort_in_month] }.reverse

build_members_efficiency(efficiency_data)
end

private

def compute_hour_value(monthly_payment, hours_per_month)
return 0 if hours_per_month.zero?

monthly_payment / hours_per_month
end

def build_members_efficiency(efficiency_data)
total_hours_produced = efficiency_data.pluck(:effort_in_month).sum
avg_hours_per_member = efficiency_data.count.positive? ? total_hours_produced / efficiency_data.count : 0
Expand Down
22 changes: 14 additions & 8 deletions app/spa/src/modules/team/team.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,6 @@ import { Demand } from "../demand/demand.types"
import { ProjectConsolidation } from "../project/projectConsolidation.types"
import { ReplenishingConsolidation } from "../replenishing/replenishingConsolidation.types"

export type TeamMembersHourlyRate = {
periodDate?: string
valuePerHourPerformed?: number
}

export type Team = {
id?: string
name?: string
Expand Down Expand Up @@ -48,6 +43,7 @@ export type Team = {
teamMonthlyInvestment?: NumberChartData
teamMemberEfficiency?: MembershipEfficiencyList
memberships?: Membership[]
membershipHourValueChartList?: MembershipHourValueChartList[]
}

export type MembershipEfficiencyList = {
Expand All @@ -65,8 +61,19 @@ export type MembershipEfficiencyData = {
realizedMoneyInMonth?: number
avgHoursPerDemand?: number
cardsCount?: number
expectedHourValue?: number
realizedHourValue?: number
hourValueRealized?: number
hourValueExpected?: number
}

type MembershipHourValueChartList = {
membership?: Membership
membershipHourValueChartData?: MembershipHourValueChartData[]
}

type MembershipHourValueChartData = {
date?: string
hourValueExpected?: number
hourValueRealized?: number
}

export type Membership = {
Expand All @@ -81,5 +88,4 @@ export type Membership = {
endDate?: string
memberRole?: number
memberRoleDescription?: string
teamMembersHourlyRateList?: TeamMembersHourlyRate[]
}
6 changes: 0 additions & 6 deletions app/spa/src/modules/teamMember/teamMember.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,6 @@ type LeadTimesChartData = {
leadTimeP95?: number
}

type TeamMemberConsolidation = {
consolidationDate?: string
valuePerHourPerformed?: number
}

export type TeamMember = {
id: string
name: string
Expand Down Expand Up @@ -48,7 +43,6 @@ export type TeamMember = {
}
demandEfforts?: DemandEffort[]
demandEffortsList?: DemandEffortsList
teamMemberConsolidationList?: TeamMemberConsolidation[]
}

type DemandEffortsList = {
Expand Down
4 changes: 0 additions & 4 deletions app/spa/src/pages/TeamMembers/TeamMemberDashboard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -150,10 +150,6 @@ const TEAM_MEMBER_QUERY = gql`
automaticUpdate
membershipEffortPercentage
}
teamMemberConsolidationList {
consolidationDate
valuePerHourPerformed
}
demandEffortsList(
fromDate: $fromDate
untilDate: $untilDate
Expand Down
2 changes: 2 additions & 0 deletions app/spa/src/pages/Teams/MemberEfficiencyTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,8 @@ export const MEMBER_EFFICIENCY_TABLE_QUERY = gql`
realizedMoneyInMonth
memberCapacityValue
cardsCount
hourValueRealized
hourValueExpected
}
}
}
Expand Down
Loading

0 comments on commit 1e82309

Please sign in to comment.