カスタムモジュール用Codexスクリプト

カスタムモジュール用Codexスクリプト

お知らせ:当社は、お客様により充実したサポート情報を迅速に提供するため、本ページのコンテンツは機械翻訳を用いて日本語に翻訳しています。正確かつ最新のサポート情報をご覧いただくには、本内容の英語版を参照してください。

Zoho ProjectsのCodeXスクリプトは、特定のルールや検証を適用するための高度な条件ロジックスクリプトです。CodeXスクリプトを使用すると、カスタムタブの作成、更新、削除の方法やタイミングを制御できます。

Info
CodeXスクリプトは、CN、JP、AEを除くすべてのデータセンターで利用できます。

Notes
こちらでは、CodeXスクリプトを使用してカスタムタブ内にビジネスルールを適用する方法を説明するため、ReviewModuleカスタムタブを例として使用します。

このタブは、変更申請、資産申請、その他のビジネスプロセスなど、組織のワークフローに適した任意のカスタムタブに置き換えることができます。

同じスクリプトを再利用しながら、要件に合わせてタブ、項目名、検証ロジックを更新してください。

ユースケース

開始日と終了日の順序の検証

データの作成時に、終了日が開始日より前にならないようにします。日付の順序が正しくないデータは拒否されます。

イベント:作成前
コード
  1. function main() {
  2. const DATE_ORDER_ERROR = 'End date cannot be earlier than start date';
  3. try {
  4. const record = current.record;
  5. const startDate = record.starting_date;
  6. const endDate = record.ending_date;
  7. if (!startDate || !endDate) return; // need both to compare
  8. const start = new Date(startDate);
  9. const end = new Date(endDate);
  10. start.setHours(0, 0, 0, 0);
  11. end.setHours(0, 0, 0, 0);
  12. if (end < start) {
  13. throw new ScriptError(DATE_ORDER_ERROR);
  14. }
  15. } catch (err) {
  16. const msg = err.getMessage ? err.getMessage() : err.message;
  17. if (msg === DATE_ORDER_ERROR) {
  18. throw new ScriptError(msg);
  19. }
  20. throw new ScriptError('Error in script, please contact portal admin');
  21. }
  22. }

更新時の過去日付の制限

ユーザーが開始日、終了日、またはレビュー完了日を過去の日付に更新できないようにします。

イベント:更新前
コード
  1. function main() {
  2. const PAST_DATE_ERROR = 'Date cannot be in the past';
  3. const DATE_FIELDS = ['review_completion_date', 'starting_date', 'ending_date'];

  4. try {
  5. const today = new Date();
  6. today.setHours(0, 0, 0, 0);

  7. for (let i = 0; i < DATE_FIELDS.length; i++) {
  8. const diff = current.affectedFields[DATE_FIELDS[i]];
  9. if (!diff) continue;

  10. const newDate = new Date(diff.newValue);
  11. newDate.setHours(0, 0, 0, 0);

  12. if (newDate < today) {
  13. throw new ScriptError(PAST_DATE_ERROR);
  14. }
  15. }
  16. } catch (err) {
  17. const msg = err.getMessage ? err.getMessage() : err.message;
  18. if (msg === PAST_DATE_ERROR) {
  19. throw new ScriptError(msg);
  20. }
  21. throw new ScriptError('Error in script, please contact portal admin');
  22. }
  23. }

更新時の開始日と終了日の順序の検証

データの更新時に、終了日が開始日より前にならないようにします。また、終了日を指定する場合は、開始日も必須になります。

イベント:更新前
コード
  1. function main() {
  2. const DATE_ORDER_ERROR = '終了日を開始日より前に設定することはできません';
  3. const START_REQUIRED_ERROR = '終了日を設定する場合は、開始日の入力が必要です';

  4. try {
  5. const record = current.record;

  6. const startDate = current.affectedFields.starting_date
  7. ? current.affectedFields.starting_date.newValue
  8. : record.starting_date;
  9. const endDate = current.affectedFields.ending_date
  10. ? current.affectedFields.ending_date.newValue
  11. : record.ending_date;

  12. if (endDate && !startDate) {
  13. throw new ScriptError('終了日を設定する場合は、開始日の入力が必要です');
  14. }

  15. if (!startDate || !endDate) return;

  16. const start = new Date(startDate);
  17. const end = new Date(endDate);
  18. start.setHours(0, 0, 0, 0);
  19. end.setHours(0, 0, 0, 0);

  20. if (end < start) {
  21. throw new ScriptError(DATE_ORDER_ERROR);
  22. }
  23. } catch (err) {
  24. const msg = err.getMessage ? err.getMessage() : err.message;
  25. if (msg === DATE_ORDER_ERROR || msg === START_REQUIRED_ERROR) {
  26. throw new ScriptError(msg);
  27. }
  28. throw new ScriptError('スクリプトでエラーが発生しました。ポータル管理者にお問い合わせください');
  29. }
  30. }

ユーザーごとの未完了データ数の制限

タブ内に未完了のデータがすでに10件を超えて存在する場合、ユーザーが新しいデータを作成できないようにします。

イベント:作成前
コード
  1. function main() {
  2. const LIMIT_REACHED = '未完了のデータが10件以上あります。上限に達したため、これ以上作成できません';
  3. const MAX_OPEN = 10;

  4. try {
  5. const url = 'https://projectsforce.localzoho.com';
  6. const portalId = current.org.zohoOrgId;
  7. const moduleId = current.record.moduleId;
  8. const currentUser = current.user;

  9. let openCount = 0;
  10. let page = 1;
  11. const perPage = 100;
  12. let hasNext = true;

  13. while (hasNext && openCount <= MAX_OPEN) {
  14. let req = new HttpRequest();
  15. req.url(`${url}/api/v3/portal/${portalId}/module/${moduleId}/entities?page=${page}&per_page=${perPage}`);
  16. req.method('GET');
  17. req.connection('zconnect');

  18. const res = req.execute().asJson()?.statusMessage?.responseText;
  19. // throw new ScriptError(req.execute().asText());
  20. const records = res.entities || res;

  21. for (let i = 0; i < records.length; i++) {
  22. const rec = records[i];
  23. const createdBy = rec.created_by && rec.created_by.zpuid;
  24. const isOpen = rec.status && rec.status.is_closed_type === false;

  25. if (isOpen && createdBy === currentUser.id) {
  26. openCount++;
  27. if (openCount > MAX_OPEN) break;
  28. }
  29. }

  30. hasNext = res.page_info ? res.page_info.has_next_page === true : false;
  31. page++;
  32. }

  33. if (openCount > MAX_OPEN) {
  34. throw new ScriptError(LIMIT_REACHED);
  35. }

  36. } catch (err) {
  37. // throw new ScriptError(err);
  38. const msg = err.getMessage ? err.getMessage() : err.message;
  39. if (msg === LIMIT_REACHED) {
  40. throw new ScriptError(msg);
  41. }
  42. throw new ScriptError('スクリプトでエラーが発生しました。ポータル管理者にお問い合わせください');
  43. }
  44. }

 作成時の過去の日付の制限

ユーザーが、開始日、終了日、またはレビュー完了日に過去の日付を設定してデータを作成できないようにします。

イベント:作成前
コード
  1. function main() {
  2. const PAST_DATE_ERROR = '過去の日付は指定できません';
  3. const DATE_FIELDS = ['review_completion_date', 'starting_date', 'ending_date'];

  4. try {
  5. const record = current.record;
  6. const today = new Date();
  7. today.setHours(0, 0, 0, 0);

  8. for (let i = 0; i < DATE_FIELDS.length; i++) {
  9. const value = record[DATE_FIELDS[i]];
  10. if (!value) continue;

  11. const newDate = new Date(value);
  12. newDate.setHours(0, 0, 0, 0);

  13. if (newDate < today) {
  14. throw new ScriptError(PAST_DATE_ERROR);
  15. }
  16. }
  17. } catch (err) {
  18. const msg = err.getMessage ? err.getMessage() : err.message;
  19. if (msg === PAST_DATE_ERROR) {
  20. throw new ScriptError(msg);
  21. }
  22. throw new ScriptError('スクリプトでエラーが発生しました。ポータル管理者にお問い合わせください');
  23. }
  24. }
データを更新できるユーザーを、作成者や担当ユーザーなど、そのデータに関連付けられているユーザー、または管理者権限を持つユーザーのみに制限します。権限のないユーザーはデータを編集できません。

イベント:更新前
コード
  1. function main() {
  2. const NOT_ALLOWED = 'このデータを編集する権限がありません';

  3. try {
  4. const url = 'https://projectsforce.localzoho.com';
  5. const record = current.record;
  6. const currentUser = current.user; // 操作ユーザー — 名前と構造を確認

  7. // 1. このデータに関連するユーザー(IDまたはZPUIDで比較)
  8. const relatedIds = new Set();
  9. if (record.created_by) relatedIds.add(record.created_by.id);
  10. if (record.review_module_cf_0002) relatedIds.add(record.review_module_cf_0002.id);
  11. if (Array.isArray(record.review_module_cf_0001)) {
  12. record.review_module_cf_0001.forEach(u => relatedIds.add(u.id));
  13. }

  14. if (relatedIds.has(currentUser.id)) {
  15. return; // 関連ユーザー -> 許可
  16. }

  17. // 2. 関連ユーザーではない -> 操作ユーザーの情報を取得し、管理者のみ許可
  18. let req = new HttpRequest();
  19. req.url(`${url}/api/v3.1/portal/${current.org.zohoOrgId}/users/${currentUser.id}`);
  20. req.method('GET');
  21. req.connection('zprojects');

  22. const user = req.execute().asJson().statusMessage.responseText; // すでにオブジェクト
  23. const role = (user.role && user.role.name || '').toLowerCase();

  24. if (role !== 'administrator') {
  25. throw new ScriptError(NOT_ALLOWED);
  26. }

  27. } catch (err) {
  28. const msg = err.getMessage ? err.getMessage() : err.message;
  29. if (msg === NOT_ALLOWED) {
  30. throw new ScriptError(msg);
  31. }
  32. throw new ScriptError('スクリプトでエラーが発生しました。ポータル管理者にお問い合わせください');
  33. }
  34. }

 

関連記事
CodeX Scriptsの概要
CodeX Scriptsの使用方法
CodeX Scripts向けJavaScript SDK
プロジェクト向けCodeX Scripts
タスク向けCodeX Scripts