休日判定ルールの変更方法最終更新日: 2020年10月28日

標準ルール

休日判定はNETWORKDAYS 関数およびWORKDAY 関数の内部で用いるルールです。標準は次のようになっています。

スクリプト WEB-INF/script/_isHoliday.js を変更することで、この判定ルールを変更することができます。標準のルールは次のようになっています。

function isHoliday() {
  var Calendar = Java.type("java.util.Calendar");
  var ret = false;
  if (holidayMap.containsKey(d)) {
    ret = true;
  } else if (icsholidayMap.containsKey(d)) {
    ret = true;
  } else {
    var cal = Calendar.getInstance();
    cal.setTime(d);
    if (cal.get(Calendar.DAY_OF_WEEK) == Calendar.SATURDAY ||
        cal.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY) {
        ret = true;
    }
  }
  return ret;
}
  • 関数 isHoliday の引数 d は日付型 (java.util.Date) です。この日付が休日ならtrueを返します。そうでなければfalseを返します。
  • 暗黙オブジェクト holidayMap はユーザが設定した休日を管理します。実体は java.util.Map オブジェクトで、キーは日付 (java.util.Date)、値は休日のタイトル文字列です。
  • 暗黙オブジェクト icsholidayMap は日本の公休日を管理します。実体は java.util.Map オブジェクトで、キーは日付 (java.util.Date)、値は休日のタイトル文字列です。
  • 暗黙オブジェクト p が利用できます。データベースアクセス時に用います。
インストール直後の Wagby にはスクリプト _isHoliday.js は含まれていません。このファイルが存在しない場合、標準で上のスクリプトと同等の処理が行われるようになっています。

ワンポイント

このスクリプトは NETWORKDAYS および WORKDAY 関数の実行時に呼び出されます。カレンダ表示処理には影響がありません。(カレンダ表示処理は標準休日ルールに則り、背景色を赤に変えています。この背景色のルールを変更することはできません。)

カスタマイズ方法

customize/webapp/WEB-INF/script/_isHoliday.js を用意します。このファイルは Designer で編集することはできません。テキストエディタで作成し、保存してください。保存時の文字エンコーディングは UTF-8 です。保存後、ビルドすることでアプリケーションに反映されます。

このスクリプトはアプリケーション起動時に一度だけ読み込まれ、内部で再利用されます。そのためスクリプトを変更したときは wagbyapp (Tomcat) の再起動が必要です。

サンプル(1) 利用者が所属するグループ名に一致する休日名称による判定

利用者 (juser) が所属するグループ名と、休日名称の文字列一致判定を行うサンプルです。

準備

グループ (jgroup) を作成します。例えば "事業所1" "事業所2" "事業所3" を用意します。利用者はいずれかのグループに所属するものとします。(Wagby の仕様では、複数のグループに所属できます。)

図1 グループの設定

次にメニューの「マスタ管理 > 休日...」から、休日を登録します。ここで名称を "事業所1" "事業所2" "事業所3" のいずれかとしてください。

図2 休日の設定

スクリプト

function isHoliday() {
  var JFCUtils = Java.type("jp.jasminesoft.jfc.JFCUtils");
  var Calendar = Java.type("java.util.Calendar");
  var ret = false;
  if (holidayMap.containsKey(d)) {
    var htitle = holidayMap.get(d);
    var jgroupnames = JFCUtils.getJuserAttribute(p,"jgroupid");//USERINFO関数
    var jgroupnameary = jgroupnames.split(" ");//空白区切り文字列を分割する
    for (var i=0; i<jgroupnameary.length; i++) {
      if (htitle.equals(jgroupnameary[i])) {//グループ名と休日名称の一致判定
        ret = true;
        break;
      }
    }
  // 以降は標準ルールを踏襲
  } else if (icsholidayMap.containsKey(d)) {
    ret = true;
  } else {
    var cal = Calendar.getInstance();
    cal.setTime(d);
    if (cal.get(Calendar.DAY_OF_WEEK) == Calendar.SATURDAY ||
        cal.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY) {
        ret = true;
    }
  }
  return ret;
}
  • 暗黙オブジェクト holidayMap から、日付をキーにして名称(文字列)を取得することができます。
  • 利用者(juser)が所属するグループ名はJFCUtils.getJuserAttribute(p,"jgroupid")で取得できます。これはUSERINFO関数の実体部となっています。戻り値は文字列型です。複数グループに所属している場合は空白区切りで連結された文字列となっています。

サンプル(2) 利用者が所属するグループ名に一致する休日種別による判定

利用者 (juser) が所属するグループ名と、休日種別の文字列一致判定を行うサンプルです。

休日モデルの「種別」は Wagby 内部では利用していませんが、このスクリプトで利用してみます。

準備

Designerのモデル一覧から「システム」タブを選択し、「休日種別 (holidaytype_m)」を選択します。初期データに "事業所1" "事業所2" "事業所3" を設定します。

図3 休日種別の設定

グループ (jgroup) を作成します。例えば "事業所1" "事業所2" "事業所3" を用意します。利用者はいずれかのグループに所属するものとします。(Wagby の仕様では、複数のグループに所属できます。)

図4 グループの設定

次にメニューの「マスタ管理 > 休日...」から、休日を登録します。ここで種別を "事業所1" "事業所2" "事業所3" のいずれかとしてください。

図5 休日の設定

スクリプト

function isHoliday() {
  var JFCUtils = Java.type("jp.jasminesoft.jfc.JFCUtils");
  var Calendar = Java.type("java.util.Calendar");
  var IPHelper = Java.type("jp.jasminesoft.jfc.IPresentationHelper");
  var jholidayEntityService = p.appctx.getBean("JholidayEntityService");
  var jholidayPHelper = p.appctx.getBean("JholidayPHelper");
  var criteriaConverter = p.appctx.getBean("JholidayCriteriaConverter");
  var JholidayMetaClass = Java.type("jp.jasminesoft.jfc.model.jholiday.JholidayMeta");
  var ret = false;
  if (holidayMap.containsKey(d)) {
    var htitle = holidayMap.get(d);
    var criteria = criteriaConverter.defaultCriteria();
    var jholidayMeta = new JholidayMetaClass();
    criteria.eq(jholidayMeta.hdate, d);
    var list = jholidayEntityService.find(criteria);//日付で検索する
    if (list !== null && list.size() > 0) {
      var jholiday = list.get(0);//先頭の1件を取得する
      var jholiday_p = jholidayPHelper.s2p(jholiday,p,IPHelper.SHOW);
    }
    var jgroupnames = JFCUtils.getJuserAttribute(p,"jgroupid");
    var jgroupnameary = jgroupnames.split(" ");
    for (var i=0; i<jgroupnameary.length; i++) {
      if (jholiday_p.type[0].content.equals(jgroupnameary[i])) {
        ret = true;
        break;
      }
    }
  // 以降は標準ルールを踏襲
  } else if (icsholidayMap.containsKey(d)) {
    ret = true;
  } else {
    var cal = Calendar.getInstance();
    cal.setTime(d);
    if (cal.get(Calendar.DAY_OF_WEEK) == Calendar.SATURDAY ||
        cal.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY) {
        ret = true;
    }
  }
  return ret;
}
  • 休日 (jholiday) の EntityService を使い、日付を検索条件に jholiday モデルを取得します。
  • ヘルパクラスの s2p メソッドを経由して、プレゼンテーションモデルに変換します。プレゼンテーションモデルには、種別の内容部(文字列表現)が含まれます。

サンプル(3) 独自のモデルを判定に利用する

システム標準の休日モデル (jholiday) とは異なる、ユーザ独自のモデルを使った休日判定を行う例を説明します。

ここでは営業日モデル (businessday) を用意しました。これは「休日だが営業日にしたい」データを登録するものとします。 つまり「営業日」に登録した日は、カレンダ上は休日(背景色が赤)ですが、営業日扱いにするというルールです。

図6 営業日モデル

スクリプト

function isHoliday() {
  var ret = false;
  if (holidayMap.containsKey(d)) {
    ret = true;
  } else if (icsholidayMap.containsKey(d)) {
    ret = true;
  } 
  if (ret) {
    // businessday モデルはこのプロジェクトで用意された「営業日」モデル。
    var BusinessdayService = p.appctx.getBean("BusinessdayEntityService");
    var BusinessdayMeta = Java.type("jp.jasminesoft.wagby.model.businessday.BusinessdayMeta");
    var meta = new BusinessdayMeta();
    var ExcelFunction = Java.type("jp.jasminesoft.util.ExcelFunction");
    var firstDayOfMonth = ExcelFunction.BOMONTH(d);// 対象日の月初の日
    var endDayOfMonth = ExcelFunction.EOMONTH(d);  // 対象日の月末の日

    //print("first="+firstDayOfMonth);
    //print("end="+endDayOfMonth);

    var criteriaConverter = p.appctx.getBean("BusinessdayCriteriaConverter");
    var criteria = criteriaConverter.defaultCriteria();
    // 対象日の月初から月末までを範囲とし、その間の「営業日」を求める。
    criteria.ge(meta.sdate, firstDayOfMonth);
    criteria.le(meta.sdate, endDayOfMonth);
    var list = BusinessdayService.find(criteria);
    if (list !== null && list.size() > 0) {
      var map = new java.util.HashMap();
      for (var i=0; i<list.size(); i++) {
        var m = list.get(i);
        map.put(m.sdate, m.title);
      }
      if (map.containsKey(d)) {
        // 休みであるが営業日、という場合、trueの値だった変数retをfalseに再セットする。
        ret = false;
      }
    }
  }
  return ret;
}
  • 項目の「開始時刻(sdate)」「終了時刻(edate)」は休日判定に用いません。
  • 要件によっては当月をまたぐ算出が必要かもしれません。その場合はBusinessdayの検索対象範囲を広げてください。例えば前後3ヶ月の範囲で NETWORKDAYS を算出する要件だと「対象日の月初から月末までが範囲」では不足するため、「対象日の *前月の* 月初から、対象日の *次月の* 月末まで」と範囲を拡げるとよいでしょう。