Skip to content

Commit

Permalink
Solve #33 - Refactor WIP limit Use Case (#40)
Browse files Browse the repository at this point in the history
* Add fetch domains wip counts from notion bot

* Add fetch domains wip limit from notion bot

* Add compare wip limit count bot

* Add format wip limit exceeded bot

* Improve test descriptions
  • Loading branch information
FelipeGuzmanSierra committed May 10, 2024
1 parent 3656d78 commit a857adf
Show file tree
Hide file tree
Showing 8 changed files with 942 additions and 0 deletions.
89 changes: 89 additions & 0 deletions lib/v2/bot/compare_wip_limit_count.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
# frozen_string_literal: true

require_relative "./base"
require_relative "../read/postgres"
require_relative "../write/postgres"

module Bot
##
# The Bot::CompareWipLimitCount class serves as a bot implementation to read domains wip limits and
# counts from a PostgresDB database, compare the values to find exceeded counts, and write them on
# a PostgresDB table with a specific format.
#
# <br>
# <b>Example</b>
#
# options = {
# read_options: {
# connection: {
# host: "localhost",
# port: 5432,
# dbname: "bas",
# user: "postgres",
# password: "postgres"
# },
# db_table: "use_cases",
# bot_name: "FetchDomainsWipLimitFromNotion"
# },
# write_options: {
# connection: {
# host: "localhost",
# port: 5432,
# dbname: "bas",
# user: "postgres",
# password: "postgres"
# },
# db_table: "use_cases",
# bot_name: "CompareWipLimitCount"
# }
# }
#
# bot = Bot::CompareWipLimitCount.new(options)
# bot.execute
#
class CompareWipLimitCount < Bot::Base
# read function to execute the PostgresDB Read component
#
def read
reader = Read::Postgres.new(read_options)

reader.execute
end

# Process function to compare the domains wip counts and limits
#
def process(read_response)
return { success: { exceeded_domain_count: {} } } if unprocessable_response(read_response.data)

domains_limits = read_response.data["domains_limits"]
domain_wip_count = read_response.data["domain_wip_count"]

exceeded_domain_count = exceedded_counts(domains_limits, domain_wip_count)

{ success: { exceeded_domain_count: } }
end

# Write function to execute the PostgresDB write component
#
def write(process_response)
write = Write::Postgres.new(write_options, process_response)

write.execute
end

private

def unprocessable_response(read_data)
read_data.nil? || read_data == {} || read_data["domains_limits"] == [] || read_data["domain_wip_count"] == []
end

def exceedded_counts(limits, counts)
counts.to_a.map do |domain_wip_count|
domain, count = domain_wip_count
domain_limit = limits[domain]

{ domain:, exceeded: count - domain_limit } if count > domain_limit
end.compact
end
end
end
121 changes: 121 additions & 0 deletions lib/v2/bot/fetch_domains_wip_counts_from_notion.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
# frozen_string_literal: true

require_relative "./base"
require_relative "../read/default"
require_relative "../utils/notion/request"
require_relative "../write/postgres"

module Bot
##
# The Bot::FetchDomainsWipCountsFromNotion class serves as a bot implementation to fetch work items
# in progress or in hold from a Notion database, count how many are by domain, and write them on a
# PostgresDB table with a specific format.
#
# <br>
# <b>Example</b>
#
# options = {
# process_options: {
# database_id: "notion database id",
# secret: "notion secret"
# },
# write_options: {
# connection: {
# host: "host",
# port: 5432,
# dbname: "bas",
# user: "postgres",
# password: "postgres"
# },
# db_table: "use_cases",
# bot_name: "FetchDomainsWipCountsFromNotion"
# }
# }
#
# bot = Bot::FetchDomainsWipCountsFromNotion.new(options)
# bot.execute
#
class FetchDomainsWipCountsFromNotion < Bot::Base
# Read function to execute the default Read component
#
def read
reader = Read::Default.new

reader.execute
end

# Process function to execute the Notion utility to fetch work item from the notion database
#
def process(_read_response)
response = Utils::Notion::Request.execute(params)

if response.code == 200
work_items_domains = normalize_response(response.parsed_response["results"])
domain_wip_count = count_domain_items(work_items_domains)

{ success: { domain_wip_count: } }
else
{ error: { message: response.parsed_response, status_code: response.code } }
end
end

# Write function to execute the PostgresDB write component
#
def write(process_response)
write = Write::Postgres.new(write_options, process_response)

write.execute
end

private

def params
{
endpoint: "databases/#{process_options[:database_id]}/query",
secret: process_options[:secret],
method: "post",
body:
}
end

def body
{
filter: {
"and": [
{ property: "OK", formula: { string: { contains: "✅" } } },
{ "or": status_conditions }
]
}
}
end

def status_conditions
[
{ property: "Status", status: { equals: "In Progress" } },
{ property: "Status", status: { equals: "On Hold" } }
]
end

def normalize_response(results)
return [] if results.nil?

results.map do |pto|
work_item_fields = pto["properties"]

{
"domain" => extract_domain_field_value(work_item_fields["Responsible domain"])
}
end
end

def extract_domain_field_value(data)
data["select"]["name"]
end

def count_domain_items(work_items_list)
domain_work_items = work_items_list.group_by { |work_item| work_item["domain"] }

domain_work_items.transform_values(&:count)
end
end
end
127 changes: 127 additions & 0 deletions lib/v2/bot/fetch_domains_wip_limit_from_notion.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
# frozen_string_literal: true

require_relative "./base"
require_relative "../read/default"
require_relative "../utils/notion/request"
require_relative "../write/postgres"

module Bot
##
# The Bot::FetchDomainsWipLimitFromNotion class serves as a bot implementation to fetch domains wip
# limits from a Notion database, merge them with the count of how many are by domain, and write them
# on a PostgresDB table with a specific format.
#
# <br>
# <b>Example</b>
#
# options = {
# read_options: {
# connection: {
# host: "host",
# port: 5432,
# dbname: "bas",
# user: "postgres",
# password: "postgres"
# },
# db_table: "use_cases",
# bot_name: "FetchDomainsWipCountsFromNotion"
# },
# process_options: {
# database_id: "notion database id",
# secret: "notion secret"
# },
# write_options: {
# connection: {
# host: "host",
# port: 5432,
# dbname: "bas",
# user: "postgres",
# password: "postgres"
# },
# db_table: "use_cases",
# bot_name: "FetchDomainsWipLimitFromNotion"
# }
# }
#
# bot = Bot::FetchDomainsWipLimitFromNotion.new(options)
# bot.execute
#
class FetchDomainsWipLimitFromNotion < Bot::Base
# read function to execute the PostgresDB Read component
#
def read
reader = Read::Postgres.new(read_options)

reader.execute
end

# Process function to execute the Notion utility to fetch domain wip limits from the notion database
#
def process(read_response)
response = Utils::Notion::Request.execute(params)

if response.code == 200
domains_limits = normalize_response(response.parsed_response["results"])

wip_limit_data = wip_count(read_response).merge({ domains_limits: })

{ success: wip_limit_data }
else
{ error: { message: response.parsed_response, status_code: response.code } }
end
end

# Write function to execute the PostgresDB write component
#
def write(process_response)
write = Write::Postgres.new(write_options, process_response)

write.execute
end

private

def params
{
endpoint: "databases/#{process_options[:database_id]}/query",
secret: process_options[:secret],
method: "post",
body:
}
end

def body
{
filter: {
property: "WIP + On Hold limit",
number: { is_not_empty: true }
}
}
end

def normalize_response(results)
return [] if results.nil?

results.reduce({}) do |domains_limits, domain_wip_limit|
domain_fields = domain_wip_limit["properties"]

domain = extract_domain_name_value(domain_fields["Name"])
limit = extract_domain_limit_value(domain_fields["WIP + On Hold limit"])

domains_limits.merge({ domain => limit })
end
end

def extract_domain_name_value(data)
data["title"].first["plain_text"]
end

def extract_domain_limit_value(data)
data["number"]
end

def wip_count(read_response)
read_response.data.nil? ? {} : read_response.data
end
end
end

0 comments on commit a857adf

Please sign in to comment.