Zoho CRMにおける販売注文を通じた完了タスクの請求によるケース管理と、Kioskによって強化された販売注文のラインアイテムとタスク間の一方向同期の作成

Zoho CRMにおける販売注文を通じた完了タスクの請求によるケース管理と、Kioskによって強化された販売注文のラインアイテムとタスク間の一方向同期の作成

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

Requirement 概要:

当社パートナーは、Zoho CRM内で「完了済み」とマークされたタスクに紐付く「Case」データに対して、請求書を生成する必要があります。そのため、以下のことを希望しています。
  1. 各該当するCaseごとにZoho CRMで自動的に受注書を作成
  2. 完了済みタスクを商品として追加し、対応する受注書に反映
  3. 請求プロセスが完了した作業内容を正確に反映するようにする
  4. 受注書の商品からタスクの変更を同期


キー詳細:

  • トリガー:Case配下のタスクが「完了済み」ステータスに更新された時
  • 操作:システムがCaseに紐付く受注書を生成し、完了済みタスクを商品として一覧化
  • 目的:タスク完了を請求対象エントリへ変換し、請求業務を効率化

タスクベース受注書生成のための実装ソリューション


完了済みタスクを請求対象商品へ変換する要件に対応するため、Zoho CRMのワークフロー機能を活用した自動化ソリューションを開発しました。実装の詳細は以下の通りです。

トリガーメカニズム:

  • システムはタスクのステータス項目の更新を監視します
  • タスクが「完了済み」ステータスへ移行した際に自動的に発動

 

自動化プロセス:

  • カスタム関数がトリガーの作動時に実行されます。
  • スクリプトはタスクデータに関連付けられているすべての商品参照を取得します。
  • 受注書作成のために商品名および詳細が抽出されます。

 

受注書生成:

  • システムは新しい受注書データを自動的に作成します。
  • 完了済みタスクにリンクされたすべての商品が受注書の商品として追加されます。
  • 受注書は元の内容ケースとの関連付けを維持します。
 

データ整合性:

  • このソリューションは、関連するすべての商品仕様を保持します。
  • 価格および数量情報は正確に移行されます。
  • 監査証跡によって自動化プロセスの表示設定が維持されます。

 

利用される技術コンポーネント:

  • Zoho CRM ワークフルールール
  • カスタムDelugeスクリプト
  • タスクと受注書間のAPI連携
  • ステータスベースのトリガー条件

 

この実装により、タスク完了と請求プロセスの間をシームレスに連携し、自動化全体でデータの正確性を維持しつつ、請求対象の作業の漏れを防ぎます。

ワークフロールールのスクリーンショット:




カスタム Deluge Script:

  1. 無効 自動化.createproductandsaleorder(Int id)
  2. {
  3. タスク = Zoho.crm.getRecordById('タスク',id);
  4. //ケースの受注書を取得
  5. asalesorder = Zoho.crm.getRelatedRecords('Sales_Orders','Cases',タスク.取得する('What_Id').取得する('id'));
  6. salesorderid = '';
  7. ordereditemslist = List();
  8. //既存の受注書が見つかった場合、リスト内の既存商品を取得
  9. if(asalesorder.size() > 0 && asalesorder != null)
  10. {
  11. salesorderid = asalesorder.取得する(0).取得する('id');
  12. salesorder = Zoho.crm.getRecordById('Sales_Orders',salesorderid);
  13. 商品 = salesorder.取得する('Product_Details');
  14. for each 商品 in 商品
  15. {
  16. prod = Map();
  17. prod.put('id',商品.取得する('id'));
  18. ordereditemslist.追加する(prod);
  19. }
  20. }
  21. //タスクが関連付け先として「Case」データの場合、完了タスクに基づき受注書データ詳細のマッピングを進めます
  22. if(タスク.取得する('$se_module') == 'Cases')
  23. {
  24. case = Zoho.crm.getRecordById('Cases',タスク.取得する('What_Id').取得する('id'));
  25. 商品 = Zoho.crm.searchRecords('商品','(Product_Name:equals:' + タスク.取得する('Case_Product') + ')');
  26. ordereditems = Map();
  27. ordereditems.put('Product_Name',商品.取得する(0).取得する('id'));
  28. ordereditems.put('数量',1);
  29. ordereditems.put('ID_Task',タスク.取得する('ID_Task'));
  30. ordereditems.put('Task_Due_Date',タスク.取得する('Due_Date'));
  31. salesorder = Map();
  32. salesorder.put('件名','SO ' + タスク.取得する('件名'));
  33. salesorder.put('Case',case.取得する('id'));
  34. salesorder.put('Contact_Name',case.取得する('Related_To').取得する('id'));
  35. //「salesorderid」がまだnullの場合 次のステップ後 折れ線グラフ 11、マッピングされたデータを基に新しい受注書を作成
  36. if(salesorderid == '')
  37. {
  38. ordereditemslist.追加する(ordereditems);
  39. salesorder.put('Ordered_Items',ordereditemslist);
  40. data = list();
  41. data.追加する(salesorder);
  42. salesorder1 = Map();
  43. salesorder1.put('data',data);
  44. createsorder = invokeurl
  45. [
  46. 種類 :POST
  47. パラメーター:sorder1.toString()
  48. connection:'modulestest'
  49. ];
  50. info 'createsorder' + createsorder;
  51. }
  52. // 受注書でステータスが「承認済み」のものが見つかった場合、新しい受注書を作成します
  53. else if(asalesorder.取得する(0).取得する('ステータス') == '承認済み')
  54. {
  55. info asalesorder.取得する(0).取得する('ステータス');
  56. ordereditemslist.クリア();
  57. ordereditemslist.追加する(ordereditems);
  58. salesorder.put('Ordered_Items',ordereditemslist);
  59. data = list();
  60. data.追加する(sorder);
  61. salesorder1 = Map();
  62. salesorder1.put('data',data);
  63. info salesorder1;
  64. createsorder = invokeurl
  65. [
  66. 種類 :POST
  67. パラメーター:salesorder1.toString()
  68. connection:'modulestest'
  69. ];
  70. info 'createsorder1' + createsorder;
  71. }
  72. // 受注書が見つかった場合、最初の利用可能な受注書を更新します
  73. else
  74. {
  75. salesorder.deleteKeys({'件名','Case'});
  76. salesorder.put('Ordered_Items',ordereditemslist);
  77. data = list();
  78. data.追加する(salesorder);
  79. salesorder1 = Map();
  80. salesorder1.put('data',data);
  81. info 'So Map :' + salesorder;
  82. updatesorder = invokeurl
  83. [
  84. 種類 :PUT
  85. パラメーター:salesorder1.toString()
  86. connection:'modulestest'
  87. ];
  88. info 'updatesorder' + updatesorder;
  89. }
  90. }
  91. else
  92. {
  93. info 'タスク が次の値と等しくない related to a Case データ';
  94. }
  95. }

フィードバックと課題:

上記のソリューションを顧客に実装した後、貴重なフィードバックを受領しました。各完了済みタスクごとに自動的に受注書を作成できる点は高く評価されましたが、変換プロセス中にユーザーインターフェースとのさらなる連携が必要だという要望も寄せられました。具体的には、次の操作ができるようにしたいとのことでした:

  • 複数のタスクを選択して、受注書に変換する。
  • 既存の受注書を選択し、タスクを商品として追加する。
  • 複数のタスクを商品として含む受注書を作成する、など。

これらの要件に対応するため、Zoho CRMの機能をさらに深く調査しました。その結果、Kiosk Studioを活用することで、顧客のニーズにマッチした有望な機能が提供されることがわかりました。Kiosk Studioを使用することで、タスクから受注書への変換をよりインタラクティブかつカスタマイズ可能にし、顧客が求めていた体験を実現できる可能性を見出しました。

Kiosk を活用した効率的な受注書作成とタスク管理

上記要件を満たすために、Kiosk はどのように実装されたか

キオスクのフローは以下のように設定されました。(スクリーンショット参照)



Kiosk 設定画面録画:



判断ポイント:

最初に、関連付け済みCaseデータに対して、すでに受注書が作成されているかどうかを確認する判断ポイントを設けました。そのために、Caseデータ内にこの目的専用のカスタム項目を追加しています。

  • カスタム項目が入力されていない場合、そのCaseデータには受注書が作成されていないことを示します。
  • カスタム項目に値が入力されている場合、そのCaseデータに既存の受注書が紐付いていることを意味します。

このカスタム項目は、受注書が作成または更新されるたびに動的に更新されます。項目の更新は、Kiosk内で処理として実行されるスクリプトを通じて行われます。これらのスクリプトにより、項目が受注書関連付け先であるCaseの現在ステータスを正確に反映します。


手順ごとの設定プロセス

設定プロセス1:

キオスクを使用して、「完了済み」ステータスかつ請求予定が利用可能なタスクを表示する画面を設計しました。これらのタスクは、下図のようにポップアップウィンドウで表示されます。

この段階で、顧客は受注書作成に含めたいタスクを選択できます。ユーザーは請求準備ができているタスクを簡単に選び、その選択に基づき受注書をスムーズに作成できます。



設定プロセス2:


すでに受注書が関連付け済みのCaseデータに対して作成されている場合は、Caseに紐付く既存受注書を表示する画面を新たに開発しました。下図のように、ユーザーは関連するすべての受注書を表示し、作業したい受注書を選択できます。

次のページでは、ユーザーが利用可能な請求対象タスクの中から、選択した受注書に追加するタスクを選択できます。これはスクリプト操作によって実現しており、選択済みタスクが受注書に適切に紐付くようになっています。


処理:

操作フローの一環としてカスタム関数を利用しています。この関数内では、前述の2画面からの入力を引数として取り込んでいます。これにより、画面間と、選択済みタスクおよび受注書を処理するロジックとの間でシームレスな連携が可能となっています。



使用中 カスタム Deluge Scripts:


1. 1つ目のスクリプトは、選択済み請求対象タスクをすべて商品として含めた受注書の作成を担当しています。


  1. //キオスク画面から渡されたデータを関数でリストとして扱う
  2. list1 = id.toList();
  3. tid = list1.取得する(0);
  4. //タスク、case、および商品を取得する
  5. タスク = Zoho.crm.getRecordById('タスク',tid);
  6. case = Zoho.crm.getRecordById('Cases',タスク.取得する('What_Id').取得する('id'));
  7. 商品 = Zoho.crm.searchRecords('商品','(Product_Name:equals:' + タスク.取得する('Case_Product') + ')');
  8. //新しい受注書を作成するためのリストとマップの作成
  9. ordereditemslist = list();
  10. ordereditems = Map();
  11. ordereditems.put('Product_Name',商品.取得する(0).取得する('id'));
  12. ordereditems.put('List_Price',商品.取得する(0).取得する('Unit_Price'));
  13. ordereditems.put('数量',1);
  14. ordereditemslist.追加する(ordereditems);
  15. salesorder = Map();
  16. salesorder.put('件名',case.取得する('件名'));
  17. salesorder.put('Case',case.取得する('id'));
  18. salesorder.put('Contact_Name',case.取得する('Related_To').取得する('id'));
  19. salesorder.put('Ordered_Items',ordereditemslist);
  20. data = list();
  21. data.追加する(salesorder);
  22. salesorder1 = Map();
  23. salesorder1.put('data',data);
  24. createsorder = invokeurl
  25. [
  26. 種類 :POST
  27. パラメーター:salesorder1.toString()
  28. connection:'modulestest'
  29. ];
  30. info createsorder;
  31. salesorderid = createsorder.取得する('data').取得する(0).取得する('詳細').取得する('id');
  32. info 'salesorderid ' + salesorderid;
  33. //カスタム項目内の受注書件数を更新します。この項目はKioskでの判断に使用されています。
  34. if(case.取得する('Total_SOs') == 0)
  35. {
  36. a = Zoho.crm.updateRecord('Cases',case.取得する('id'),{'Total_SOs':1});
  37. info a;
  38. }
  39. else
  40. {
  41. asalesorder = Zoho.crm.getRelatedRecords('Sales_Orders','Cases',タスク.取得する('What_Id').取得する('id'));
  42. //info updatetask;
  43. asalesordersize = asalesorder.size();
  44. //info asalesordersize;
  45. updcase = Zoho.crm.updateRecord('Cases',case.取得する('id'),{'Total_SOs':asalesordersize + 1});
  46. }
  47. //タスクのチェックボックスを更新し、それが受注書に追加されたことを示します。このチェックボックスは、Kioskの画面表示条件でタスクを表示するために使用されています。
  48. updatetask = Zoho.crm.updateRecord('タスク',tid,{'Added_to_SO':真});
  49. //リスト1に複数のタスクIDが含まれている場合、それらを同じ受注書に追加するには、受注書を更新してください。
  50. for each index i in list1
  51. {
  52. if(i >= 1)
  53. {
  54.   info i;
  55.   tid1 = list1.取得する(i);
  56.   タスク = Zoho.crm.getRecordById('タスク',tid1);
  57.   //info 'tid1:'+ タスク;
  58.   case = Zoho.crm.getRecordById('Cases',タスク.取得する('What_Id').取得する('id'));
  59.   商品 = Zoho.crm.searchRecords('商品','(Product_Name:equals:' + タスク.取得する('Case_Product') + ')');
  60.   ordereditemslist = list();
  61.   ordereditems= Map();
  62.   ordereditems.put('Product_Name',商品.取得する(0).取得する('id'));
  63.   ordereditems.put('List_Price',商品.取得する(0).取得する('Unit_Price'));
  64. ordereditems.put('数量',1);
  65.   ordereditemslist.追加する(ordereditems);
  66.   salesorder = Map();
  67.   salesorder.put('Ordered_Items',ordereditemslist);
  68.   data = list();
  69.   data.追加する(salesorder);
  70.   salesorder1 = Map();
  71.   salesorder1.put('data',data);
  72.   info salesorder1;
  73.   updatesorder = invokeurl
  74.   [
  75.   種類 :PUT
  76.   パラメーター:salesorder1.toString()
  77.   connection:'modulestest'
  78.   ];
  79.   //info 'updatesorder' + updatesorder;
  80.   updatetask1 = Zoho.crm.updateRecord('タスク',tid1,{'Added_to_SO':真});
  81.   info '更新する Task1: ' + updatetask;
  82. }
  83. else
  84. {
  85.   info '失敗';
  86. }
  87. }

2. これにより、タスク選択者と顧客が自動的に新規作成された受注書に追加され、請求対象タスクの管理が効率化されます。

  1. //キオスク画面から渡されたデータをリストとして機能するよう変換
  2. list1 = id.toList();
  3. //list1に1つ以上のタスクIDが見つかった場合、同じ受注書に追加して更新
  4. for each index i in list1
  5. {
  6. tid = list1.取得する(i);
  7. タスク = Zoho.crm.getRecordById('タスク',tid);
  8. case = Zoho.crm.getRecordById('Cases',タスク.取得する('What_Id').取得する('id'));
  9. 商品 = Zoho.crm.searchRecords('商品','(Product_Name:equals:' + タスク.取得する('Case_Product') + ')');
  10. ordereditemslist = list();
  11. ordereditems = Map();
  12. ordereditems.put('Product_Name',商品.取得する(0).取得する('id'));
  13. ordereditems.put('List_Price',商品.取得する(0).取得する('Unit_Price'));
  14. ordereditems.put('数量',1);
  15. ordereditemslist.追加する(ordereditems);
  16. salesorder = Map();
  17. salesorder.put('Ordered_Items',ordereditemslist);
  18. data = list();
  19. data.追加する(salesorder);
  20. salesorder1 = Map();
  21. salesorder1.put('data',data);
  22. info salesorder1;
  23. // 下記APIで使用されている'salesorderid'は、キオスク画面から引数として直接渡されます
  24. updatesorder = invokeurl
  25. [
  26. 種類 :PUT
  27. パラメーター:salesorder1.toString()
  28. connection:'modulestest'
  29. ];
  30. info 'updatesorder' + updatesorder;
  31. updatetask = Zoho.crm.updateRecord('タスク',tid,{'Added_to_SO':真});
  32. }

この方法により、タスク選択および受注書作成プロセスを自動化し、効率的なユーザー体験と正確なデータ管理が実現します。

キオスク操作画面の録画:



Syncing タスク変更の受注書商品への反映(Client Script 活用)


顧客から、受注書の商品に行った変更を、それらの商品から作成されたタスクにも反映させたいという要望がありました。この要件に対応するため、client scriptを導入し、サブフォームの「OnCell変更する」イベントでトリガーが発動するように設定しています。

このスクリプトにより、受注書商品から関連付けられたタスクへの一方向の同期が実現します。受注書内の折れ線グラフ商品に変更が加えられると、対応するタスクも自動的に更新され、受注書と紐づくタスク間の整合性が確保されます。

この仕組みにより、受注書データとタスクの正確性・一貫性が保たれ、商品が更新されるたびにタスク側にも自動で反映されます。

Client Script 設定ページ:




使用中 Client Script:


  1. //折れ線グラフ商品のタスクIDを取得し、一意の識別子としてタスクの取得・更新に使用
  2. const tasknum = ZDK.Page.getSubform('Ordered_Items').getRow(index).getCell('ID_Task').getValue();
  3. //取得する項目を定義
  4. if (field_name == '数量') {
  5. var タスク = ZDK.Apps.CRM.タスク.searchByCriteria('((Task_Number:equals:'+tasknum+'))');
  6. var task1 = タスク[0];
  7. var taskid = タスク[0]._id;
  8. const 数量 = ZDK.Page.getSubform('Ordered_Items').getRow(index).getCell('数量').getValue();
  9. task1.数量 = 数量;
  10. var response = ZDK.Apps.CRM.タスク.updateById(task1, taskid);
  11. console.log(response);
  12. }else if (field_name == 'Task_Due_Date') {
  13. var タスク = ZDK.Apps.CRM.タスク.searchByCriteria('((Task_Number:equals:'+tasknum+'))');
  14. var task1 = タスク[0];
  15. var taskid = タスク[0]._id;
  16. const ddate = ZDK.Page.getSubform('Ordered_Items').getRow(index).getCell('Task_Due_Date').getValue();
  17. console.log(ddate)
  18. const newdate = ddate.substring(6,10)+'-'+ddate.substring(3,5)+'-'+ddate.substring(0,2);
  19. task1.Due_Date = newdate;
  20. console.log(task1);
  21. var response = ZDK.Apps.CRM.タスク.updateById(task1, taskid);
  22. console.log(response);
  23. }else if (field_name == 'サービス') {
  24. var タスク = ZDK.Apps.CRM.タスク.searchByCriteria('((Task_Number:equals:'+tasknum+'))');
  25. var task1 = タスク[0];
  26. var taskid = タスク[0]._id;
  27. const サービス = ZDK.Page.getSubform('Ordered_Items').getRow(index).getCell('サービス').getValue();
  28. console.log(サービス)
  29. task1.サービス = サービス;
  30. var response = ZDK.Apps.CRM.タスク.updateById(task1, taskid);
  31. console.log(response);
  32. }else if (field_name == '説明') {
  33. var タスク = ZDK.Apps.CRM.タスク.searchByCriteria('((Task_No:equals:'+tasknum+'))');
  34. var task1 = タスク[0];
  35. var taskid = タスク[0]._id;
  36. const des = ZDK.Page.getSubform('Ordered_Items').getRow(index).getCell('説明').getValue();
  37. console.log(des)
  38. task1.件名 = サービス;
  39. var response = ZDK.Apps.CRM.タスク.updateById(task1, taskid);
  40. console.log(response);
  41. }



Quote
カスタムSolution作成者 Nick | Zoho パートナーサポート

ご不明な点がございましたら、どうぞご遠慮なく パートナー-サポート@zohocorp.comまでご連絡ください。

Notesまた、ヨーロッパおよびイギリスのパートナーの方は、 パートナー-サポート@eu.zohocorp.comまでお問い合わせください。