【GraphQL】Carelyの過重労働機能のQueryを一部紹介 | Dev Driven 開発・デザインチーム 【GraphQL】Carelyの過重労働機能のQueryを一部紹介 | 働くひとと組織の健康を創る iCARE

BLOG

【GraphQL】Carelyの過重労働機能のQueryを一部紹介

メグミ
2020/09/30

こんにちは!サーバーサイドエンジニアのメグミです!

今月の頭にCarelyの過重労働機能をリニューアルしました!
今回は、その中で行ったGraphQL化についてQueryを一部を紹介しながら説明したいと思います。

はじめに

過重労働機能とは

人事や産業医が従業員の残業時間や疲労蓄積度を管理するための機能です。
簡単にまとめると以下のような機能があります。

  • 残業時間の確認
  • 長時間労働者の自動抽出
  • 疲労蓄積度チェックテスト
  • 残業時間のインポート/エクスポート
  • 残業情報のメール送信

今回紹介すること

REST API から GraphQL Ruby での実装に変更

リニューアル前はRESTでの実装でしたが、GraphQLでの実装に変更となりました。
今回はその中の一部Queryの実装をご紹介します。

CarelyのGraphQLの構成

Carely では graphiql-rails というgemを使用しています。
構成については以下のとおりです。

従業員の残業時間の取得

データの参照は GraphQLのQuery で行います。

まず、query_type.rbfield を定義し、必要に応じて argument の定義をします。
field名のメソッドを定義し処理を記述します。

# query_type.rb

module Types
  class QueryType < Types::BaseObject
    field :overtimes, Types::OvertimesType, null: true, description: "当該月の残業時間" do
      argument :year, Int, required: true, description: "年"
      argument :month, Int, required: true, description: "月"
    end

    def overtimes(**args)
      Queries::OvertimesQuery.new(user: context[:current_user]).policy_scoped_overtimes(args)
    end
  end
end

上記のQueryが返すのは OvertimesType という型なので type を定義します。

# overtimes_type.rb

module Types
  class OvertimesType < Types::BaseObject
    field :overworker_count, Int, null: true, description: "過重労働者数"
    field :customer_count, Int, null: true, description: "従業員数"
    field :overtimes, [OvertimeType], null: true, description: "残業時間情報"
  end
end

上記の type にある OvertimeType も定義します。

# overtime_type.rb

module Types
  class OvertimeType < Types::BaseObject
    description "残業時間情報"
    field :hour, Float, null: true, description: "残業時間"
    field :year, String, null: true, description: "年"
    field :year_month, Types::Date, null: true, description: "年月"
    field :customer, Types::CustomerType, null: true, description: "従業員情報"
  end
end

実際の処理(Query Processing)を overtimes_query.rb に記述します。

# overtimes_query.rb

module Queries
  class OvertimesQuery < Queries::BaseObject
    def policy_scoped_overtimes(**args)
      year_month = Overtime.年月を作成するメソッド(args[:year], args[:month])
      monthly_overtimes = Overtimes.where(year_month: year_month)

      # 当該年月での過重労働者数
      overworker_count = monthly_overtimes.where("hour >= ?", 45).count
      # 当該年月での従業員数
      customer_count = Customer.joins(:overtimes).merge(monthly_overtimes).count

      {
        overworker_count: overworker_count,
        customer_count: customer_count,
        overtimes: overtimes
      }
    end
  end
end

この処理で最終的に返す値はquery_type.rb で定義した OvertimesType に合わせます。

overtimes のデータモデルは以下のとおりです。

# overtime.rb

# == Schema Information
#
# Table name: overtimes
#
#  id                                 :integer          not null, primary key
#  hour(残業時間)                     :decimal(5, 2)    default(0.0), not null
#  year_month                         :date             not null
#  created_at                         :datetime         not null
#  updated_at                         :datetime         not null
#  customer_id                        :integer          not null
#
# Foreign Keys
#
#  fk_rails_...  (customer_id => customers.id)
#

class Overtime < ApplicationRecord
  belongs_to :customer
  # 省略
end

GraphiQL(/graphiql)でQueryを実行すると残業時間情報を取得することができます。
先ほど query_type.rb で定義した fieldargument を指定し実行します。

query {
  overtimes(fiscalYear: 2020, month: 4) {
    overworkerCount
    customerCount
    overtimes{
      yearMonth
      hour
      customer{
        fullname
      }
    }
  }
}

実行結果が data として取得できます。

{
  "data": {
    "overtimes": {
      "overworkerCount": 2,
      "customerCount": 2,
      "overtimes": [
        {
          "hour": 81,
          "customer": {
            "email": "employee-101@example.com",
            "employeeNumber": "101",
            "fullname": "従業員 太郎"
          }
        },
        {
          "hour": 80.5,
          "customer": {
            "email": "employee-201@example.com",
            "employeeNumber": "201",
            "fullname": "人事 太郎"
          }
        }
      ]
    }
  }
}

さいごに

以上、過重労働機能のGraphQLのQueryの一部を紹介しました!

おわり