Articles tagged with: 業務改善

「真鶴でチャレンジの総量を真鶴で」イベントでkintoneを説明しました


2024年1月25日に『チャレンジの総量を真鶴で』に登壇しました。


今回のイベントは、昨夏に開催された『kintone Café 神奈川 Vol.15』と同じ場所である真鶴町観光案内所の二階にある会議室で行われました。
(kintone Café 神奈川 Vol.15の開催に関する詳細は、このブログでご覧いただけます。)

上記のブログにも載っていますが、その盛り上がりが冬の山北町での『kintone Café 神奈川 Vol.16』へと繋がり、一緒に企画した株式会社あわえさんとの共同作業を経て、真鶴町の活性化にkintoneを活用しようという思いが強まりました。
その思いを具体的にするため取り組んでいたのが、真鶴町でkintoneを使った地域創生への試みです。
昨夏のイベントで一緒に企画した株式会社あわえさんと、真鶴町をkintoneを使って活性化させたいとの思いが一致しました。コンセプトや開催内容など、何回も打ち合わせを重ねました。一度は開催日程も決まったのですが、開催を目前にして延期の決断を下したこともありました。

そうした困難を乗り越え、真鶴でまたkintoneのイベントを企画しようとした理由は、真鶴が抱える過疎地としての課題や危機感をkintone Café 神奈川のイベントの中で共有できていたからです。


地域活性化の手法は各地域や知見を持ったかたがそれぞれのやり方で実践しています。
その中で弊社や私やギボンズ社の藤村さんが地域活性化の手段として提供できるのは情報技術、それもkintoneを使った業務改善においてです。
実際に真鶴町の事業者さんに行っていただいた事前ヒアリングによると、まだビジネスの中では昔からのやり方が主流だそうです。そのやり方を改善するだけでも地域のために貢献できる余地があるはずと考えました。


今回のイベントには最終的に二社の真鶴の事業者の方に参加していただきました。
他にも数社に申し込んでいただいていましたが、都合が合わず、まずは二社から。

しかもご多忙とのことで、時間も二時間半ほどでした。
その限られた時間で、kintoneについての機能や使い方、可能性についてを語りました。その特徴や魅力なども交えて。

おかげでkintoneについてはその良さを理解してもらいましたが、今回の開催によって導入していただくには到りませんでした。
小規模な事業での導入に関しては、既存のツールから月額7500円を支払って移行することが難しいという意見もありました。

ただ、私の後にギボンズ社の藤村さんがマンダラアートについてワークをしてくださったことで、風向きが変わりました。ワークによって違う発想が刺激されたことも良かったのでしょう。
実際、ワークによってご自身の仕事の洗い出しができた結果、kintoneを使うことも選択肢の一つとして見直すきっかけになったようです。
私の話によってkintoneの魅力は理解していただけたので、思考のフレームワークを使って考えを整理してもらえれば有力なツールとして選ばれる。それこそが今回のイベントの効果だと思います。


私もワークの有効性を感じました。後は真鶴のこれからについてより一層の対話を進め、真鶴町の状況にあった道を探っていきたいと思いました。
一朝一夕で行うにはテーマが大きいので、一日で成果はでません。何回も何回も繰り返し真鶴の皆さんと会話する必要があると感じています。

皆さんが帰られた後は、私とギボンズ社の藤村さん、あわえ社の三宅さん、松木さんと四人で真鶴の街を楽しみました。
以下は上のイベントとは少し関係性が薄いのですが、真鶴の地域創生の可能性を感じた良い機会だったので、少し長い文章になっています。よかったらください。

今回の会場である真鶴町観光協会のすぐそばにあるのが、sumi marcheさん。昨夏のkintone Café 神奈川の懇親会でも利用させてもらいましたが、その時は人数が多かったので、離れのスペースでの開催でした。


ところが今回はsumi marcheさんの中でおいしい料理とお酒を頂きました。時間はまだ16時。平日のこんな時間に飲むことなどめったにありません。
ですが、この時間に飲むことこそが真鶴時間。私も真鶴の時間を身体に刻むため、あえてこの時間から飲む道を選びました。
鯖やはばのり、イカ。海産物は目の前の海から上がってきます。刻一刻と暗くなっていく空や海を見ながら、会話を楽しみ、時間を気にせずに飲む真鶴の夕暮れ。
都会でビジネスの風に吹かれているとつい忘れてしまうゆとりです。

地方創生にあたって都会の価値観を持ち込むと失敗する。よく聞く言葉です。
都会の価値観とは平日の夕方からお酒を飲む時間の使い方とは一線を画しているはずです。

続いて向かったのは青木商店 GLIDE。こちらのお店は前に来た時には気づきませんでした。松木さんにうかがったところ、最近できたらしいです。
こうした新たなお店ができるのは、真鶴のためにも喜ばしいことです。

実は、この日真鶴駅で藤村さんと待ち合わせた私たちは、おおみち通りという街の目抜き通りでいつも活気があったお魚屋さんが代表の方がお亡くなりになったとかで休業する旨の張り紙をみたばかりでした。
お昼は伊藤商店というデビット伊東さんのお店でラーメンを頂きました。こちらのお店が真鶴で存在感を示していますし、これまでの数回の訪問でポツンポツンと頑張るお店も観てきました。ですが、真鶴の街の全体が衰退しつつあることは、数回訪れただけでも感じていました。
ですが、このように少しずつ町もお店もリノベーションされ、少しずつ点るあかりが戻っています。


こちらのお店ではジャックダニエルのハイボールとソフトクリームをいただきました。この取り合わせがまたうまかった!また今度来たいと思います。


そして最後に訪れたのが駅前にある塩と檸檬さん。このお店は前に来た時にも気になっていました。お酒も料理もとてもおいしかった!
たまたまお隣にいらっしゃったのが松木さんや三宅さんもご存知の方で、その方も交えて楽しいお酒の時間が持てました。
こうしてみると、真鶴もまだまだ行くべきお店が多いこと、街は決して未来をあきらめていないことが分かります。

実際、第一次作業に課題を抱えているとはいえ、都会から気軽に訪れられる過疎地というポジションは真鶴ならではの長所にもなります。
そのような街で、私に何ができるのか。kintoneを武器に、これからも何回も訪れることになるでしょう。

今日はご参加いただいた皆様、ありがとうございました。
今回のイベントを通じて、真鶴町の地域創生に向けての新たな一歩を踏み出すことができました。今後も真鶴の可能性を信じ、kintoneを活用して地域活性化に貢献していきたいと考えています。


CHALLenGERSに参加してきました


2023年12月18日に『CHALLenGERS』に参加してきました。
詳細は告知サイトをご覧ください。

『CHALLenGERS』の主催はエン・ジャパン様。
このビルには過去に何度か訪れたことがありますが、エン・ジャパン様のオフィスを訪れるのは今回が初めてでした。
私は別案件との調整があり、前の週になるまで参加できるかどうか判りませんでした。

無事に参加できることになり、『CHALLenGERS』のスケジュール表を見てみると、メインスピーカー4名、LTスピーカー7名というとても豪華な陣容。
それぞれの方が、kintoneを使って業務改善をしていく際に味わった人しれぬ苦労や、kintoneから学んだ気づきなどを惜しげもなく公開してくださり、学びの多いイベントだったと思います。

今回のスピーカーの皆さんの多くは、技術者ではありません。
技術者でない方々も、むしろそれゆえに業務改善に大きく貢献できる事実。kintoneを筆頭にしたノーコードツールは、プログラミング、いや、データベースへの深い知識がなくても業務システムを作れる環境を作りました。

技術者ではない方々が主役となったkintoneのイベント。これこそが裾野の広がりです。
一時期、私はkintone Caféのテーマを技術者向けにして主催していました。しかし挫折しました。そこで反省し、最近はユーザー目線のkintone Caféを開くようにしています。すると、開催がスムーズになってきました。

技術者がkintoneを使うようになるのは、あるツールの変革にすぎません。ですが、システムを作ることができなかった現場の皆さんがkintoneを使うようになるのは革命です。

日常の業務はマニュアルがあったとしても、それは作業手順にすぎません。しかもそのマニュアルを使う側でしかなく、マニュアルを作る側にはなれません。
それを作る側になるきっかけとなるのが、kintoneに作業を作り替えることではないかと思います。
kintoneで作ることで、業務を再構築し、さらに業務を見直すことでマニュアルを作る側にも変われる。

なぜこう書くかというと、マニュアルを作ることの効力を教えられたからです。
エン・ジャパンに入社して日も浅いちったろ_たなみんさんとおかそんさんの登壇は、私に衝撃を与えました。入社して四日目でkintone開発養成講座一日目を受講し、さらに上司と実案件の現場に同席させられるスピード感には驚かされました。
私にとって育成は経営者になってからの大きな悩みです。これほどの速成のノウハウが知りたいのは当然です。
お二人が登壇の中で紹介していた「無印良品は、仕組みが9割」。この本を私はさっそく『CHALLenGERS』の翌日に買い求め、帰りの電車の中で読み込みました。

マニュアルとは考えさせるツールであり、マニュアルには答えを書かない。このことに私が逆に考えさせられました。
あいまいさを残さないからこそマニュアルのはず。あいまいさの排除は、5000弱あるエン・ジャパン内で活用されている内部のkintoneアプリに一切のJavaScriptを許可しない思い切りに表れています。かと思いきや、そのマニュアルには答えをそのまま書かないところ。つまりあいまいさや考える余地を残していること。

この二つの相反する命題が両立していることに、エン・ジャパンさんの研修の秘密があるのかなと思いました。それが私が当該本を買った理由です。
標準化とはいったい何を指すのか。おそらく考え方の軸というか芯を指すのではないか。それが私が感じたことです。ただしもしそうだとしたら、それを文章化し、明示化するのはとても大変なはず。

『CHALLenGERS』で推奨されていたのは「ナイスチャレンジ」です。私もその言葉に相当に感化されました。この正月のチャレンジとして、中途で途絶えていた開発ガイドラインを仕上げてしまおうと思うほどには。
暗黙知をどのように文書化するかが重要です。ただの作業手順を超えた、より深い内容をマニュアルに反映させる必要を感じました。

その動機を頂いたのが『CHALLenGERS』の良さでした。
エン・ジャパンの皆さん、登壇者の皆さん、ご参加者の皆さん、ありがとうございました。

イベント後、終電ギリギリまで新宿で過ごしました。3次会か4次会まで参加したかは忘れましたが、ギリギリ帰れてよかったです。さすがに新宿で始発チャレンジや野宿チャレンジを敢行するのが『CHALLenGERS』のナイスチャレンジではないはず。

こちらにXポストまとめサイトを載せています。


Ship Vol.2に参加してきました


2023年12月8日に『Ship Vol.2』に参加してきました。

会場はサイボウズ社本社。前日のMOVED MeetUpも同じ場所だったので、二日連続の訪問です。

今回のShipへの参加は私にとって初めてです。4/21にVol.1が催された際は、私に参加する余裕がなかったため、弊社のメンバーに代わりに参加してもらいました。

あれから約8カ月近く経ち、弊社の状況にも変化が生じました。
そして私自身の考えも変化しました。

どう変わったかと言うと、kintoneシステム開発においてJavaScriptを主に使ったカスタマイズの限界を悟りました。

つまり、もう、案件の数が増えすぎて、JavaScriptだけで対応しきれなくなりました。
そもそもkintone自体が、容易に変化するお客様の仕様に柔軟に対応することを前提にしています。kintoneが変わるなら、カスタマイズ要件も頻繁に変わります。
どれだけ要件定義を入念に行ってもそれは変わりません。お客様自身が確定させたつもりの仕様も、社会情勢の変動によって変更を余儀なくされます。しかもその速度はますます速まっている昨今です。
kintoneシステム開発のやり方もアジャイル開発の考えが主流になっている今、いちど決まった要件が覆らないかつての常識は通用しません。
そして、JavaScript開発ではどうしてもその速度においてプラグインにかないません。つまり、JavaScript開発を続けていると、いつまでたっても生産性が上がりません。

弊社はJavaScriptで頑張ってやってきました。うちのメンバーもJavaScript開発では多層Promiseを扱った実装もこなしてくれるようになっています。
が、今年に入ってエンジニアの育成が必要になった途端、JavaScriptを書く前提の育成の速度ではプラグインに及ばない現実にやられました。
ということは、JavaScriptでやり切れるとすれば、最初からスキルのあるエンジニアを抱えている場合のみです。
この半年でその現実を痛感しました。

JavaScriptに成り代わり、kintoneのカスタマイズを行う手段はいろいろとあります。大きく分けるとプラグインか外部サービスでしょうか。
外部サービスは著名なところではgusuku Customineやトヨクモシリーズがあります。
一方、プラグインは有償無償を問わず、各社様から多種多様のプラグインが提供されています。

krewDataやkrewSheetは、一つのプラグインだけで、アプリ連携やデータ連携処理を何重にもつなげて行えることが特徴です。
と、偉そうなことを書いていますが、実は私がkrewDataを触り始めたのはつい最近です。この半年どころか、2カ月以内です。

gusuku Customineは5、6年ほど前から触っていたにもかかわらず、krewDataを触るのが遅れたのは、弊社のお客様が使っていらっしゃらなかったことが理由です。

ところが、今年になって二つの案件でkrewDataを扱うことになり、私も実際に触ることになりました。そして、その機能に舌を巻きました。

実際、krewDataはよくできていると思います。
フローをつなげていき、上流の設定値が変わったら、連結される下流のフローに一気に反映する点もなかなか魅力的です。
慣れてくると、JavaScriptよりもかなり簡単です。

正直にいうと、krewDataで実現できることはJavaScriptでも書けます。フローの連携もできます。
ところが、案件によっては、複雑な連携を何十にも連ねる実装をJavaScriptで書こうとするとかなりのコード量になるでしょう。
その中のどこか1カ所でもPromiseのReturnを置く位置を間違えれば、またはResolveやRejectの値を間違えれば、途端によくない結果を招きます。

また、せっかく実装してもお客様側の仕様が変更になると、その全てがやり直しになってしまいます。
krewDataは、そうしたコーディングにまつわるあらゆる手間を省いてくれます。私がkrewDataの機能に舌を巻いたのもそれが理由です。

上記のようないきさつをへて変化しつつあった私の心を待っていたかのように、今回、Ship開催のアナウンスがありました。
そして、私自身がまだグレープシティ、現在のメシウス社の文化や社風を十分に理解していません。
そこで、今回はShipに参加しようと思いました。
ところが、私の調整がなかなかつかずにいるうちに、ページからShipが申し込めなくなってしまいました。

今回は運営するメシウス様のご好意で、後から追加枠として入れていただけることになりました。感謝いたします。

さて、今回はサイボウズ社27Fに繁るシンボル「サイボウ樹」の前に集ってのセミナー形式。私にとってこの形式は久々です。


最初にメシウス社の佐藤さんと大江さんより開会の挨拶。


そして、株式会社ZOZOの新井さん(あーけん)からは「krewDataのすゝめ」。
ふむ、Char関数はVBAを扱う際にはよく使いますが、krewDataでも使えるんですね。
そして、膨大なデータチェック自体もkrewDataだけで完結できる可能性を見せてもらえたのは、まさにイベントならではの気づきです。あーけんさんに感謝です。


続いて、NPO法人チャリティーサンタの青山さんから「全国のサンタクロースを支えるkintone 開発」。
こちらは主にkrewSheetをお使いの事例でした。
krewSheetは、私も以前からお客様の案件によっては導入したりして使っていました。
Excelからkintoneにチャレンジしたお客様に、高いハードルを与えずにkintoneになじんでもらう際、krewSheetは最適なツールです。
krewSheetを使って運用を直観的にしながら、集計もkrewDataを効果的に使っていらっしゃる良い事例でした。
また、チーム応援ライセンスが適用できるユーザーはkrewシリーズが安価に使えるプランがあることを私はあまり認識していませんでした。この可能性を知った事も、ありがたい情報でした。青山さんに感謝です。


続いて、マルテー大塚の石井さんより「キントーンとアクセスの話」。
上に書いた通り、私はkrewDataを使っていて、kintoneではできなかったSQLを活用した可能性に驚きました。
kintoneではOUTER JOINもUNIONもできません。Group ByもHavingもそれを使ったデータ加工やアプリ連携をするにあたってはJavaScriptやAlaSQLなどのライブラリが必要です。
石井さんのセッションでは、こうしたSQLを起点としたさまざまな事例を取り上げてくださいました。
私もそうですが、RDBやSQLに慣れている者にとってkintoneの癖と呼べる点こそ、このSQL的なアプローチができない点です。
技術者にさらにkintoneを使っていただくうえで、石井さんのセッションは参考になるはずです。石井さん、ありがとうございました。


続いてメシウス社の佐藤さんより「krewのマーケチームではこうやって予実管理してます」。
これも、Excelでは直感的にできていたのに、kintoneでは直感的な操作ができないと考える人への好事例ですね。
こうした事例は、最終的なデータ加工や見せ方に関する部分なので、私もそこまで積極的にお客様に提案してこなかったのですが、より最後の一塩の意味をこめて、今後は提案していきたいと思いました。
佐藤さんには今回追加枠のご案内もいただきました。それも含めてありがとうございました。


さて、その後はkrewラベル付きのビールやジュースが配られ、交流タイムです。
5つほど属性ごとに分かれて集まってもらい、そこで輪になって語ってもらう趣旨がアナウンスされました。
さて、私の属性はkintone初心者ではないし、情シスでもありません。どちらかといえばkrewData初心者のようなもの。近くにたまたま近くにいたいた中尾さんと、どのグループに行きましょうかね~とのんきに話していたら、いつのまにかグループが定まっていました。なので、私は中尾さんに加え、同じようにはみ子になってしまったお二方と四人で話をしていました。


なるほど、こういう運営方法なのですね。理解できたところで、次の懇親会第二部の時間になりました。
ところが私はこの日の夜、横浜で忘年会の約束がありました。そのため、ここで辞去しました。

雰囲気も把握したし、また次の機会があれば参加したいと思います。メシウスさん、参加者の皆さん、ありがとうございました。


2023 kintone hive TOKYO


2023 kintone hive TOKYO

kintonehiveでは
お久しぶりの方々や、はじめましての方々にお会いすることができました。

事例共有の場ですが、リアルに人と触れ合える場です。
去年は登壇者、今年は応援者と仙台でのイベントスタッフとして参加。
生が一番感情や熱量が伝わるのでやはりいいですね。

なるべくTwitterで発信しつつ、登壇者へ写真を送りつけるために写真撮りまくってました。
プロのカメラマンが取ってくれたものは登壇者へ共有はされるのですが、会場の様子などユーザーがとっている様子はまた別で感じるものがあることを知っているので。

登壇者の同期ができるってすごく良い刺激にもなるし、同じ体験をした仲間ができるってこれからの人生をより良いものにしてくれます。和気あいあい感がTOKYOでも感じられたのは良かった。
人数も圧巻でしたね。1000人て。仙台の3倍。首都圏の強みですね。
登壇者からは前列3列目までがギリギリ見えるのでなんかうじゃうじゃいるなーくらいの感じだったかもしれませんが。

登壇者のかのってぃさんに僕の登壇経験の話や身振り手振りは思った3倍大きく。歩くタイミング、資料切り替えタイミングなどお伝えしていたのを活かしてくれていたのも嬉しかったですね。

導入成功のポイントをそれぞれお話していただいてましたが、最も大事なのはなんのために。が最重要だと思っています。その後に色々付属してくるものだと。熱意もその一つですし、業務フローもその一つ。

社内での成功はそう。

社外からの支援は上記も大事ですが、言われたことをやるのではなく、+の提案や見直し。(付加価値)
コンサルのような形とクライアントがしっかりと向き合うこと。しっかりとは開発業者に任せるではなく、共にということです。
使うのはクライアント。良くするのもクライアント。
どのようなスタンスの企業かによってkintoneでもなんでも成功できるかどうかは変わってくると思います。

成長するには質の良い仕事しかない。質の良いクライアントしかない。と感じています。
質の悪い一方的なものは苦しい経験であり、再現性はありません。
再現性を高めることができれば型が出来てくるということであり、スピードも上がるということに繋がります。

どれだけクライアントとの目線をあわせられるか、業務を理解できるか。そして俯瞰して全体を見渡せるか。
改めて再認識したkintonehiveでございました。

ご挨拶の時間があまりありませんでしたが、登壇者3名と新たに直接の繋がりをつくることができました。
そのうち一名は長井さんへお繋ぎ済みです。

著:水沢光幸

Twitterでのkintonehive情報発信は下記










kintone hive Tokyoに会社で参加しました


7/5に行われたkintone hive Tokyoに参加しました。今回は弊社からは8名のメンバーで参加しました。

今年の4月に5名の新メンバーを加え、弊社は新生アクアビットとして次のステップを踏みました。そのうち2名はリモートワークで普段の業務にあたっています。
また、弊社は毎週定例会議を行っており、リモートメンバーもそこにはオンラインで参加しています。
つまり、まだ実際には会ったことがありません。そのため、今回のkintone hive Tokyoを顔合わせの機会にしたいと思いました。

通常は私一人であれば、早めにkintone hiveの会場に入り、全国から来られたkintoneプレイヤーの皆さんと交流をします。
ところが今回は、弊社内でのコミュニケーションの熟成を優先しました。会場のZepp DiverCity Tokyoでも私たちは二階席から観覧し、皆さんとの交流よりも自社内の交流に時間を割きました。

うちのメンバーのほとんどは、Cybozu Daysに参加したことがありません。また、kintone hiveに関しても私ともう1名を除いては初めての経験です。

今回は何よりも、独特の雰囲気で進行するkintone hiveの雰囲気に誰かが違和感を覚えないか、フォローが必要でした。
一昨年のCybozu Daysで私が犯した失敗を繰り返さないようにしなければなりません。

お台場のDiver Cityのフードコートで好きに話してもらい、Zepp DiverCity Tokyoの二階席でもまずメンバー間のコミュニケーションを図ることに注力しました。そして、互いの相性や会話のスキル、キャラクターを見極めることに専念しました。

今回、弊社のメンバーに事前に以下の内容を伝えておきました。

@channel

前にもお伝えしたと思いますが、
hiveはユーザーが自社にkintoneを導入した事でこう変わった、という発表の場です。

何をユーザーは求めているのか、という観点で見てもらえればと思います。

最先端の技術を入れたからすごいのではなく、
業務を改善し、業務プロセスとシステムを組み合わせて最適化したことに注目してほしいです。
お客様のユーザーからの目線です。

技術者はつい自分の技術の成果やスキルアップに目を向けがちです。ただし、それは個人的な時間の中で行うべきです。
仕事として業務を受ける際は、予算を考慮しながらあらゆる手段を組み合わせ、設計・実装・試験を最も早く確実な手段で行わねばなりません。しかも、保守も可能な限り、お客様に担っていただけるような形が望ましいです。

メンバーが私から伝えた内容とどう受け止め、hiveを観覧した内容から何を感じるか。
私はそれが楽しみでもあり、その反応に応じて、仕事の進め方も考えたいと思っていました。

さて、kintone hive Tokyoが始まりました。


まずは、社会福祉法人八越会 ちどり保育園 吉岡 敦志さんです。

まず、kintoneを知育玩具に例えたスライドのタイトルに惹かれます。

お子さんをお持ちの方ならご存じとは思いますが、保育園や幼稚園の先生と保護者のやりとりは、必要ではあるものの効率化が求められる業務の典型です。
先生方も大変であり、保護者にも忙しい出勤の合間に余裕がありません。誰もが満足していない状況です。

吉岡さんのセッションには、他にも共感を得やすい要素が満載でした。
既存のパッケージ化されたシステムだと、どうしても業務を変える必要に迫られます。kintoneを使えば実際の業務にシステムを合わせながら、同時に業務の効率化を達成できます。
吉岡さんはお互いが求める着地点をkintoneに見出しています。

吉岡さんから保育士さんにオペレーションを移管することで、20倍の効率化を実現し、さらにChobiit for kintoneを使うことで220倍の処理効率を達成しておられる。
冒頭から素晴らしいプレゼンテーションでした。

弊社メンバーには、現在お子さんを保育園に通わせている方がいて、とても共感していたようです。
吉岡さん、ありがとうございました。


続いては、株式会社エクソルの田中幹也さん

まず、利きちくわが多少できるというつかみに惹かれます。

kintoneと各種プラグインを使いこなし、売り上げ換算にして1億円以上の作業時間削減を達成した成果にもインパクトを受けました。その成果も大したものですが、情報システム部が成し遂げた成果の大きさが、社長室直属の部署配置換えにつながった点もアピール度が高いです。
情報システム部とは今や、単なるシステム屋ではありません。上手く使えば全社の業務を一気に変え、勝てる組織に変貌させるからです。
その導入効果と社内の浸透を認め、社長室の直属にしたエクソル社の社長様の慧眼にも賞賛です。


あと「期待通り」を少し超える方針も、共感を呼びます。
もともと営業(かまぼこ)から情シスへ転身した田中さんですが、営業で培ったノウハウをうまく社内へのkintone浸透と導入に活かしておられます。とても良い事例でした。

田中さんとは後日のトヨクモさんのイベントでもお会いしましたが、その時の私はかなり疲弊していたため、まともな会話になりませんでした。申し訳なかったですが、またお会いしたいです。特にかまぼこ営業についての話はゆっくりとお伺いしたいです。
田中さん、ありがとうございました。


続いては、弁護士法人宇都宮東法律事務所の伊藤一星さんです。

宇都宮には私は昨年の春に一週間ほど滞在していました。そのため、個人的には強い興味がありました。
弊社は今、2社の弁護士法人さんの案件を並行でやっています。さらに、hiveの後に別の1社の弁護士法人様から引き合いをいただきました。

おかげで、弊社には弁護士法人にとどまらず、法曹業界全体にわたった事務処理の知見が貯まっています。
その視点からも、伊藤さんの話される内容にはうなずける点が多々ありました。
法曹業界の場合、弁護士法人がいくら業務改善を行おうとも、周辺の関係機関のIT化の進展が芳しくない課題があります。
そして、その兼ね合いがとても大変だと言うのも理解しています。

そのため、まず利益相反チェックから始めるアプローチは、最初の一歩として分かりやすかったです。
伊藤さん、ありがとうございました。


さて、ここで最初の休憩が入りました。
メンバーの反応を見たところ、なかなか良さそうです。kintone hiveやkintoneエコシステムについて過剰に拒否反応を示すこともなさそう。むしろ、勉強になっていると前向きな反応を示しているようにも見えます。
私にとっては、8人で来て良かったと思う瞬間でした。
そんな休憩時間、ロビーに出て、何人かの方と交流を深めました。うちのメンバーも時間があれば紹介しました。


休憩の後は、株式会社モリビの植田剛士さん

とにかく植田さんは語りがとても上手で、観客の心をつかむ術に長けておられました。
また、伝えたい内容を伝えるための印象的なスライドの見せ方も上手で、それによって皆さんはの心に後々まで登壇内容が残っていました。それが結果につながったように思います。
人の心の掴み方と、人への伝え方の美味さには、同じスピーカーとして感心させられ通しでした。。

住職であることと、話が上手いことや声が通ることに相関関係があるのかはわかりません。ですが、その話し方は選ばれた理由の一つでしょう。
ただ、植田さんの発表内容は、単に話が上手いだけでなく、業務改善の内容にも注目するべきです。さらに、業務改善の効果がわかりやすい形で示されていたことも特筆しておきたいです。
業務改善の効果を紙の削減として示すのに、コルコバードのキリスト像の高さやスペースシャトルの長さに例えるスライドも秀逸でした。また、社内の動きの推移をイラストで見せるあたりなども、プレゼンの見本だというべきでした。
植田さん、ありがとうございました。


続いては、埼玉県鶴ヶ島市役所の中嶋英行さん

中嶋さんの発表も見事でした。
介護保険課の業務を改善する際に避けて通れないのが、年配の方が多くを占める審査会の改善です。
ところが、一度はkintone導入が流れてしまいます。ところがその逆境を乗り超え、中嶋さんは諦めずに不屈の精神で再度提案に持ち込みます。コミュニティの力も借りながら。
そして、運用にまで繋げます。その粘りとガッツは、kintone界隈でも屈指ではないかと瞠目しました。

市役所などの場合、一般企業よりも導入へのハードルが高く、根回しも大変であることはわかります。使う側への配慮やマニュアルの作成など、作りながら直すkintoneの良さを生かした方法がうまくはまらないもどかしさも感じました。

中嶋さんが苦労されたように、年配の方が大多数を占めているために、改革の進まない業務の多いこと。まだ全国に無数にあるはずです。
それを粘り強く進めれば、理解が得られ、改善も可能であることを中嶋さんは示してくださいました。
自治体の制約を打破して見事なアプリを作り上げた中嶋さんに拍手。

そして、それを全国向けに横展開しようとする志も素晴らしいと思います。
ぜひ、この志をkintoneをまだ知らない人々に広めるため、お力添えいただければと思います。

個人的には、鶴ヶ島という時点でkintone Café 埼玉とのご縁で親近感を持ちました。
中嶋さん、ありがとうございました。


続いて株式会社プロダクション・エース 鹿野内 春奈さん

かのってぃさんです。
昨秋のCybozu Daysでは弊社ブースのブランディング・飾り付けに多大なるご協力をいただきました。
今回、hiveに登壇することについても、春先にはすでにかのってぃさんから聞いていました。

私は今日のかのってぃさんの登壇内容についてはまったく関与していません。つまり、今日の発表が私にとってかのってぃさんの発表を聞く最初の機会です。

かのってぃさんの登壇内容は、会社の中での業務改善を推進する者ならば共感できる悩みに満ちていました。閉じた場である会社にいると得にくい業務改善についての情報。
そこでかのってぃさんはコミュニティに助けを求めました。kintoneエコシステムの一翼をなすコミュニティの力に。
この展開は、私やkintone界隈でコミュニティに関わっている人たちには大いに賛同できます。転職したり、私のように起業したり。kintoneとコミュニティによって人生が変わった人たちの事例は枚挙にいとまがありません。

が、会場の多くを占める方々にとっては、自社での改善事例が知りたいわけです。その解決のヒントがコミュニティにあるのは間違いない。ところがその救いをコミュニティに求める流れが、未体験の方にはピンとこないのでしょう。
私たちは、会社の外にまで効果を及ぼすコミュニティの力を外に知らせてあげたいと願っています。ところが、わが国の場合、コミュニティの力が軽んじられているため、なかなかその認知が進んでいません。
そもそも、弊社のメンバーからして、コミュニティの力をあまりよくわかっていないと思われるのですから。


社外との交流をkintoneを介して行う。
かのってぃさんの登壇は、孤独なkintone試用者が、社内と社外で仲間を増やしていくための貴重な知見にあふれていました。
コミュニティとは自分や自社の営業のためではありません。ましてや自己顕示のためでもありません。自分と周囲の意識改革のためにこそ、コミュニティは本領を発揮するのです。
かのってぃさんの登壇は動画にも残されています。コミュニティがなぜ重要なのか、と問われた時、かのってぃさんのこの姿を見せれば伝わるはず。
かのってぃさん、ありがとうございました。


続いては、株式会社ZOZO 三品 秀樹さん
最後を締める三品さんの登壇は、まさにラストにふさわしいノリの良さといでたちが、神としての勢いに満ちていました。

自らを神と位置付ける圧倒的な自信は、演出のためでしょう。とはいえ、圧倒的な実績に裏打ちされているがゆえの神であることも伝わってきました。
三品さんの登壇で印象に残ったのは、徹底的な業務理解の必要性です。


これは、当たり前と言えば当たり前すぎることなのです。が、私たちは頭の中の理屈だけで大切だとわかっていて、なかなか実践には至れません。
凄いと思ったのが、プロパーである三品さんが自社の業務を徹底理解することは当然として、それを外部のベンダーにも徹底してもらっている点です。

ベンダーの担当者はおそらくZOZO様専任なのでしょう。ほかの顧客の業務はほとんどしていないのではないでしょうか。
そうでなければ一社の業務を徹底的に理解することは難しいはずです。
少なくとも、今の私には一社の業務を徹底理解する時間はありません。

ですが、業務改善を行うには、業務を徹底的に理解する必要がある。そのプロセスをへて、ようやく圧倒的な実績が打ち立てられるのも事実です。
三品さん、ありがとうございました。

さて、kintone hive Tokyoが終わった後は、アフターhive交流会や参加者ごとの懇親会が定番です。
ところが、今回は冒頭に書いた通り、弊社内の交流を深めることに専念する千載一遇の機会です。


というわけで、アクアシティお台場のシズラーにて、夜までメンバー間の交流をしていました。
そして後日、全員からhiveの感想文を出してもらいました。
その感想文を読み、まずはあのkintone hiveの雰囲気に引いた人がいなかったことに安堵しました。そして、皆さんそれぞれにhiveから得るものを得たことにこれからの弊社の未来が見えました。

とはいえ、頭で考える以上にシステム開発と業務改善を組み合わせることは難しいことは知っておいてもらわないと。
単に受け取った仕様をコーディングして納品するシステムの在り方は終わりを迎えようとしているのですから。

そのためにも、メンバーには何度も何度もユーザーの業務課題を考え、それをシステムに落とし込む実践を繰り返してもらい、そのつながりを頭に叩き込んでもらにしなければ。
人工知能に問い合わせる間に自分の頭で答えが出せる程度には。

まずはkintone hive Tokyoの登壇者の皆さん、会場でお会いした皆さん、運営のサイボウズ社の皆さん、その他ご縁の会った皆さん、ありがとうございました。


トヨクモkintoneユーザーフェス2023に登壇しました


6/27と28の両日にオンラインで開催されたトヨクモkintoneユーザーフェス2023に登壇しました。


私の登壇は事前に収録したものです。
四月のある日、目黒のトヨクモ社に伺って、収録に臨みました。
本格的なスタジオでの収録は私にとってあまり経験がないもので、視線の使い方や振る舞いなどが完全に未知の領域でした。
全てが手探りの状態でした。

事前に資料は作っていましたが、それを事前に読み上げる練習をする時間がありませんでした。リハーサルは当日の収録直前の一度だけ行いました。

その後の座談会では、事前の控え室の会話では良い感じの話ができたような気がするのに、スタジオでは私の振る舞いは少し怪しかったようです。

そんな私でしたが、トヨクモkintoneユーザーフェス2023に登壇するにあたり、話す内容に困ることはありませんでした。
なぜなら、kintoneとその周囲のエコシステムを支持する私にとって、トヨクモさんは大切なパートナーであり、お客様に提案する際にはトヨクモさんの製品群は必ず検討するからです。

kintoneのエコシステムの中には、多くの会社様が多彩なプラグインやサービスを提供しています。
その中にはトヨクモさんのサービスと機能的には近いものもあります。
私たちはお客様の要望に基づき、それらのサービスを選び抜き、適したものを提案します。

サービスを選択する際には、機能面を重視することは当たり前です。
しかし、それだけではありません。
その背後には、kintoneとそのエコシステムの価値観や文化への深い共感が必要です。
つまり、サイボウズ社の掲げる「チームワークあふれる社会を創る」ことに役立つかどうか。kintoneの欠点を補う機能があるかどうかを考える必要があります。
サービスがこられの要件を満たしているなら、提案することにためらいはありません。

私と一緒に登壇した石井さんやなかじさんも、同じ考えを共有しているはず。だからこそ、ぶっつけ本番の座談会もうまくまとまったのだと思います。

まずは一緒に登壇した石井さん、なかじさん、ありがとうございました。これからも一緒にkintoneやトヨクモさんを盛り上げていきましょう。


続いて、二日間にわたるさまざまなセッションです。
私がトヨクモkintoneユーザーフェス2023のアーカイブ動画を見たのは、十日ほどたった後でした。

お一人お一人の登壇内容についてはここでは触れません。

一つだけ、印象に残った事を記しておきます。それは、皆さんが語りの中で既にkintone をインフラとして扱っていることです。
トヨクモさんの各サービスを使って業務改善を行う際、kintoneはもはやインフラとして不可欠な存在なのです。

私が普段関わるkintoneのイベントでは、kintoneはインフラとして扱われていません。あくまでも業務改善のプラットフォームやサービスとして扱われています。
他社が主催するkintoneプラグインや連携サービスのセミナーでも同様です。kintoneはサービスとして扱われます。各社のサービスはkintoneというサービスを補完するツールとしてのサービスなのです。

ところが、トヨクモkintoneユーザーフェス2023での皆さんの話を聞いていると、kintoneは完全にインフラとして扱われているように感じました。つまり、電話線やインターネット環境と同じくらい当たり前のものとして認識されていました。
もちろん、kintone上にはアプリがあり、何らかの業務改善が行われているでしょう。しかし、トヨクモさんのフェスでは、トヨクモさんのサービスに焦点を当てるためか、kintoneはあまり語られません。

kintoneはもはやインフラとして位置づけられている。この気づきは強い印象を私に与えました。
kintoneは基盤としてのインフラであり、トヨクモさんのサービスはその基盤の上で動くプラットホームまたはサービスなのです。
確かに、kintoneはプラットホームより上位のインフラとしての地位を築いてきたのかもしれません。少なくとも、トヨクモさんのサービスにとっては、kintoneは欠かせないインフラになっています。
これはkintoneの素晴らしさを示す証拠でもあります。


7/10には、登壇者を含めた後夜祭が開催されました。
トヨクモkintoneユーザーフェス2023はオンラインで開催されましたが、きちんと後夜祭という形でオフラインの場を設けていただいたことはとても良かったです。
それによって、登壇者と視聴者とのリアルのコミニケーションが取れました。また、登壇者としても自身の登壇内容について振り返ることができたように思います。
後夜祭がトヨクモさんの本社の暖簾の中ではなく、サイボウズさんで開催されたことも印象的でした。
kintoneは既にプラットホームではなく、インフラになり、トヨクモさんが主催するユーザーフェスもそのインフラの中で行われているのです。


まさに登壇内容から受けた印象が、後夜祭によって裏付けられました。

引き続き、kintoneというインフラの中で、kintoneの初期からよく知るトヨクモさんがより良いサービスを展開してくれることを願っています。
今回は登壇へのお誘いと開催準備、そして素敵な後夜祭まで、ありがとうございました。


kintone hive osakaに参加しました


5/23にZeppなんばにて行われたkintone hive Osakaに参加しました。

先日、kintone hive sendaiに参加しましたが、その記憶も新しいうちに、また貴重な経験ができました。

Zeppなんばは私も初めての訪問です。学生時代に何度となく訪れたこのあたりも年月に応じて一新されました。しかし、裏通りに行くとかつての雰囲気が残されていて、少し郷愁に浸る事ができました。

そばのタリーズでギリギリまで打ち合わせしていたため、私が会場に入った時は、始まってから5分近く経過していました。

壇上ではサイボウズ関西支社の松森さんがkintone hive Osakaを楽しむためのお話をされていました。
各地のhiveでサイボウズの社員さんが登壇し、会場の盛り上げに貢献しておられます。背景にはサイボウズの各社員さんの準備もあって、いろいろ大変なんだろうなぁと想像します。ロビーでも社員のみなさんとお会いする事ができました。


一人目の登壇者は認定NPO法人おてらおやつクラブ 桂 浄薫さんと茶円 春希さん。
桂さんは奈良天理にある善福寺の住職を務めておられます。袈裟を着ての登壇はなかなか新鮮。

おてらおやつクラブさんは、お寺にお供えされる檀家さんからの食料などを貧困に苦しむ家庭におすそ分けする活動をしておられます。
https://otera-oyatsu.club

今回の登壇では、そのあたりについての貴重なお話を伺う事ができました。

ポイントは大きく二つに分けられます。
一つは、困っていらっしゃる方にどのようにして匿名で届けるか。
もう一つは、多数のkintoneへのリクエストをどうやってさばくか。
この点が聴きどころでした。


WordPressを絡めてウェブからデータを取り込む事例は弊社でも多くを手掛けております。
おてらおやつクラブさんの事例が秀逸なのは、kintoneの一日一万リクエストの制限を間にWordPressに備わっているデータベースを挟んでのバッチ処理で行っている事です。

桂さんの思いをkintone未経験だった茶円さんが形にした。
まさに技術者として望ましい形だと思いました。

「たすけて」のハードルを下げられる。
「たすけたい」をごく自然にできる。

私も去年、kintone Café 神奈川を鎌倉の安国論寺さんで開催させてもらいました。kintoneとお寺は相性がよいことは実証済みです。

桂さん、茶円さん、ありがとうございました!


続いては、八代製薬株式会社 喜田 晃大さん。
なんときったんさんではないですか!
私、登壇を促す声を聞くまできったんさんが登壇することを知りませんでした。事前にhiveの資料を見ていなかったので。

言うまでもなく、きったんさんはkintone エバンジェリストとしてともに活動する仲間であります。

きったんさんはこの度の登壇で、エバンジェリストであってもkintone hiveに参加できる、と言う新たな可能性を見せてくれました。
私の中に巣食っていた「kintoneエバンジェリストはkintone hiveに出られない」という思い込みに対して、きったんさんはNOを突きつけてくれました。

きったんさんの成功ストーリーは明確です。
コロナを機に、在宅勤務の仕組みを進めるためにkintoneを導入し、規定も含めて水面下で調査しました。
まずは目的を明確にするステップです。
続いて、どの業務からkintoneに置き換えるかの洗い出しをしました。
これも目的を明確にするステップです。
そして、やりがいと楽しさを伴った形で、業務改善の成果を出しました。
目的が明確になった事で、経営層や上司への説明も容易になり、モチベーションにもつながります。

見事なkintone導入の成功事例です。
実は八代製薬さんの事例は、krewDataを駆使した在庫管理の好事例であることも見逃せません。

今後もきったんさんとは各地のkintoneイベントでご一緒できそうです。
一緒に盛り上げていきましょう!

きったんさん、ありがとうございました!


続いては、関西電力株式会社 藤井 伸弥さんと中野 一高さんです。

関西電力さんといえば、日本のインフラを担う大企業です。関西で育った私の体の何割かは、関電成分からできています。

これほどまでの大企業で、しかも、社会のインフラを担っていらっしゃる関西電力さんが万が一にも停電などの事態を招こうものなら、社会に与える影響は必至です。

つまり、基幹システムは必須です。ですが、基幹システムだけだと小回りが効きません。硬直した仕組みになってしまいます。


そこで関電さんはRPAをうまく活用し、基幹システムに影響を与えず、基幹システムのデータをうまくkintoneに取り入れる仕組みを構築されています。

こうした企業でも、顧客との関係は欠かせません。
外部のウェブサービスからどのようにしてデータを持ってくるか。その活用方法において、kintoneと基幹システムを組み合わせることはできるはず。
そのモデルケースと言える取り組みを見せてもらえました。

お二人の掛け合いで進む登壇は、台本を読んでいるようなぎこちなさもありました。でも、それがまたこ愛嬌です。
私はまだkintone hiveに登壇した事がなく、多くの観客の前にkintoneの事例を話す緊張を知りません。その決断と勇気に敬意を表します。

インフラを担う大企業がここまでkintoneを使っている事例を見せてくれたことに、日本の変化を感じました。

藤井さん、中野さんありがとうございました!

続いては、神戸市役所 小阪 真吾さんと小寺 有美香さんです。

神戸市の方がkintoneのイベントに出るのは二回目です。
かつて、神戸市の教育委員会でAccessのフォームにデータを入れるオペレーターをやっていた私にとっては、特に感慨深いです。

コロナによる自治体の取りまとめ対応が大変だったことは、私たちの記憶にも新しいです。
神戸市でも同じ悩みがありました。

神戸市が有利だったのは、kintoneをコロナ前から導入していたことです。
そして、小阪さんの立場が企画調整局のデジタル戦略部だったことも有利に働きました。
混乱の極みにある西区保健福祉部に対し、お手伝いしましょうか?と申し出たやり方も良かったのでしょう。

小阪さんの上から目線でもなく、押し付けがましくない接し方が現場の抵抗感を和らげたことは間違いありません。
コミュニケーションを頻繁に取ることで保健福祉部の現場の皆さんからの信頼を勝ち得たそうですが、最初の入り方もコミュニケーションとしてこういるべき形だったのでしょう。

私としては、小阪さんがおっしゃっていたスクラム開発が印象に残りました。
弊社もそれに近いことをやっているのですが、なんちゃってスクラムになっているため、結果としてスクラムの可能性を活かしきれていません。
スクラムを深く理解し、実践することも必要なのでは、と言う気づきを得ました。

小阪さん、小寺さん、ありがとうございました!


続いては、有限会社アートワークス 宗政 伊織さんです。

「家具工房がkintoneを入れてみたハナシ」というタイトルです。

スライドにも登場する稲沢さんが伴走支援で入られているそうです。稲沢さんがおっしゃるには、タイトルのハナシがカタカナになっていることもポイントだとか。

スライドを紹介する宗政さんは新卒二年目。初々しさが際立っていました。話す間合いも壇上の動作も独特の間合い。その立ち居振る舞いが会場を癒やし、かつ共感を集めていました。

この宗政さんの間合いは、伴走支援をされた稲沢さんの柔らかい印象と合っていました。相性が合うとはこのことでしょうか。
稲沢さんは対面の打ち合わせの際に大量のお菓子をお持ちするそうです。頭を使うから甘いものを持ち込む配慮が素晴らしい。
とても和やかな対面開発の雰囲気が想像できます。私も参考にしたいと思いました。

宗政さんの壇上の振る舞いも、単に癒やされるだけではありません。やるべきところはやる。作ったアプリは正義と言い張る強気。押すべきところは職人さんに入力を指示する芯の強さも感じさせました。
私たち観客は、宗政さんの壇上からの癒やしと、稲沢さんの和やかな対面開発の雰囲気。それに対照となる業務改善を進める信念の強さのコントラストに強い印象を受けたのでしょう。
多くの支持を集めたのもわかります。

宗政さん、ありがとうございました!


続いては株式会社神戸製鋼所 今井 健太さんと田淵 裕子さんです。

神戸製鋼所さんも大企業です。

私もかつての常駐先で神戸製鋼所出身の方と数年間一緒に仕事をしていたので、その社風は少しだけ知っていたつもりでした。
日本の高度成長期を担った企業であるがために、最近のクラウドやノーコードの流れとは対極にある企業だと勝手に考えていました。
しかし、その考えは改めなければなりません。

むしろ、kintoneで商売をしている弊社にとっては、神戸製鋼所さんの事例から学ぶべき点が多くありました。

昔話の花咲か爺さんをモチーフにストーリー仕立てにした内容もわかりやすかったし、
業務部門と導入部門の思惑の乖離から、一度は挫折し、そこから復活を遂げるストーリーもわかりやすく、共感を呼びました。

現場にフィットさせることは、製造ラインが確立している神戸製鋼所のような会社では最優先事項のはずです。


そのために企画部門とシステム部門、そして現場に納得してもらうために、さまざまな手法をメソッドとして確立しておられます。

それらは理にかなっていると思いましたし、現場の方に共感を呼ぶための心配りが至る所に見られました。

神戸製鋼所さんの場合、取り組みにも秀でた点がありました。例えば、社内で独自に設けたkintone資格の制度などはその筆頭に挙げられます。

私は神戸製鋼所さんの発表を聞きながら、非常に感銘を受けました。
今、弊社がご協力させていただいているお客様にこの内容を一刻も早く聞いてほしい。そして、7月に行われるkintone hive Tokyoを聞いていただきたいとも。

今井さん、田淵さん、ありがとうございました!


さて、投票結果の集計中は、サイボウズのゆっきーさん、ぽえみーさんが関西でkintone Café を主宰するyamaさん、がっきーさん、中尾さんの3名をパネリストに迎え、関西のkintone コミュニティの現状を紹介する「kintone Caféってなんなん?」です。

私自身、関西で20数年を育ちながら、関西のリアルkintone Caféに参加した経験はありません。このkintone hive Osakaの翌日にkintone Café Osakaに参加したのが初めて。
なので、まだまだこれから何度も参加しなければ、という決意が募るセッションでした。

夜は、私がAfter hive 交流会に申し込んでいなかったことと、そもそもトラブルが勃発してしまい、22時半ごろまでなんば近辺にいました。

でも、それも含めてもよい関西kintoneの夜を過ごせました。
出会った皆様、本当にありがとうございました!


kintone hive sendaiに参加しました


4/13に仙台PITにて行われたkintone hive sendaiに参加しました。

私にとって、初めてのkintone hiveへの現地参戦。
それまで、私にとってのkintone hiveといえば、幕張メッセで行われるCybozu Daysの中で開かれるkintone AWARDでした。

各地のkintone hiveで選ばれた方によるえりすぐりの大会。毎年そのレベルの高さは知っていました。
ところが、ここ三年、私はkintone AWARDをよくみられていません。それは、Cybozu Daysでブースを出展するようになり、ブースの対応で見られなくなったからです。

そんな私が初めて予選であるkintone hiveを観戦したのは昨年。kintone hive tokyoでした。
今、ジョイゾー社にいらっしゃる根崎さんが感動的な登壇を成し遂げた日とした記憶にも鮮やかです。
他の登壇者のレベルも高い。
そこで気付かされたのは、幕張のkintone AWARDだけでなく、各地で行われるkintone hiveも見なければ、ということです。

そこで今年は、kintone hive sendaiに合わせて東北からの複数のご縁を調整しました。
前々日には郡山市で。そして前日は米沢市で商談。その流れで最終日には仙台市で。kintone hive sendaiに参加できることになったのです。
それまでの二日間、頭の中はkintoneにどっぷりつかっていました。そして、会場の仙台PITの熱気や雰囲気は、kintoneにまみれた頭をさらに活性化させてくれました。


プライベートでライブハウスには何度も行ったことがあります。が、kintone hiveのようなIT系イベントてライブハウスに来るのは初めて。
会場の雰囲気はまさにライブ。心は湧き立つ一方。
やはり来て良かったと思わされました。

冒頭に登場したサイボウズ東北支社の田澤さんの話もバッチリ。メリハリの利いた話は、盛り上げ方を指南しつつ、会場の気持ちを高め、ライブ感をさらに盛り上げる名MCです。


一人目の登壇者は株式会社グローバルフィールドの保坂 梨恵さん。インパクトのあるいでたちで登場。
少し緊張していらっしゃるようですが、それがまたライブ会場の良さです。緊張していらっしゃる様子は、ディスプレイを通して見ると気づきません。会場の肌感覚とでもいいましょうか。
慰謝料のかわりに会社を受けついだというくだりでは、聴衆の心も鮮やかにつかんでいらっしゃいました。

保坂さんの登壇は、kintoneの良いところ、つまり簡単にレポートが表示できる利点を活かしている点で分かりやすかったです。
kintoneに変えたことでご本人が出産された際も、数カ月の間、会社に一切出社せずに業務が回せたそうです。引き継いだ時は紙の山だった業務を解きほぐし。

その結果、社員の皆さんの仕事も週休2.5日で回せるようになったそうです。kintoneの導入効果をフルに享受していらっしゃいます。
同じ経営する身として、社長がいなくても会社が回る体制はまさに理想。

保坂さんの属しておられる業種は、弊社にとってもなじみのある業界です。
その観点から拝聴した保坂さんの登壇内容からは、お客様はどういうところをkintoneの価値として置かれているのかがわかり、とても参考になりました。

保坂さん、ありがとうございました!


続いては、旭川信用金庫 古田 真之さん。
なんとkintone hiveに信用金庫の方が登壇されるのは初めてだそう。
こちらも私にとってはとても興味深いお話でした。というのも、弊社でも今、まさに信用金庫さんに近しい案件を担当させていただいているからです。

どのようにセキュリティやコンプライアンス上の懸念を払拭し、未知のツールを導入するのか。
それをどのようにして稟議を通し、組織全体に広めていくのか。
私もその難しさを感じながら、日々の提案や作業を行っています。

実際、旭川信用金庫さんでも、一度は導入に挫折したそうです。
そこで終わらずに、再び細かいアプリの作成からやり直し、徐々に組織内部で認知度を高め、ついには、当初挫折したアプリの再構築に取り掛かってらっしゃる最中だそうです。
まさにkintoneの導入のお手本ともいうべき内容。
話の構成がきっちりしているところは信用金庫さんの堅確性を持たせつつ、合間に笑いを入れる構成も素晴らしい。


ここに書かれている通り、金融機関とクラウドデータの組み合わせは、今後、私たちとしてもさらに社会に向けて働きかけていかなければならない部分だと思っています。
今後、旭川信用金庫さんがどのように導入してゆくか。その行く末が楽しみでなりません。

古田さん、ありがとうございました!


続いては、株式会社ニイヤマハウス 長南 卓弥さんです。
こちら、今回の登壇された方の中では、もっとも技術者に寄った内容でした。何しろ、長南さんはもともとパチンコなどの遊技機のプログラミングを行っておられたそうです。

ゲーム業界出身である長南さんのプレゼンは、ドット絵をうまく取り入れつつ、動きがあってとてもわかりやすい内容でした。プレゼンの妙味を感じさせてくれました。
Google CalendarとExcelと紙と基幹システム。まさにkintoneに切り替えると効果が発揮しやすい取り合わせです。
長南さんが素晴らしいのは、プログラミングができるIT経験者でありながら、アナログでのコミュニケーションをおろそかにせず、根気よく導入に向けて努力されたところです。

その苦労が実り、kintoneの導入が軌道に乗り始めるとよくあること。それはポータルサイトが大渋滞する件です。
ポータルを整理してあげると、お客様の満足度があがる。私もそんな経験を何度もしてきています。
ところが、なかなかポータルサイトの整備に手が回らないのも事実。これは、デザインが苦手な私にとっても由々しき問題です。

長南さんのkintone portal desingerを使った改善は、このところkintone portal desingerを全然使っていなかった私にとって大いなる気づきを与えてくれました。
長南さん、ありがとうございました!


続いては、東北特殊鋼株式会社 桜井 利江さん/木田 司さんです。

kintone導入歴一年と一年半という二人の掛け合いは、先輩と後輩のほほえましい関係を思わせて楽しかったです。
私もまだ掛け合いプレゼンはやったことがありません。一度はやってみたいと思います。プレゼンに躍動感が出ますから。

さて、お二人の登壇の何が素晴らしかったって、こちらの会社様は社長様からの声掛けが絶妙だったことです。
トップが業務改善へのやる気を持ち、そこから社内にkintone喫茶を結成し、多様な立場で情報共有する体制を作った。


私の中で今回のkintone hiveで刺さった言葉は数多く挙げられます。その一つはこちらで紹介されていたkintone喫茶。もちろんkintone Caféを運営する身としては見逃せません。

kintone喫茶によって現場の中で情報共有の機運を高め、業務改善につなげる。
素晴らしいと感じたのは、kintoneから帳票を出せるようにした後、その内容をもとに現場からのフィードバックをもらい、リスクアセスメントの評価につなげたところです。
出した帳票をもとに、現場から安全性を高めるためのフィードバックを受け、それをアプリや帳票に反映する。まさにあるべき業務改善のスパイラルです。
安全は全てに優先される。この言葉はあらゆる業種に通じるはずです。kintoneは安全管理にも使えるよい事例でした。

社内をkintone 喫茶で改善した東北特殊鋼さんの事例は、kintone Café運営にとっても役立つことでしょう。

桜井さん、木田さん、ありがとうございました!


続いては、株式会社昇栄 山崎 梨英さんです。

プレゼンのタイトルを見た瞬間、私のボルテージは上がりました。
「ライトコースでどこまでできるか、基本機能の極限活用が生み出したものとは!?」
私が苦手意識を持っているのはライトコースです。苦手というより、手がけたことがない、というのが正解です。

何しろ、今まで自社や多くのお客様の環境でkintoneに触れてきましたが、ライトコースはまだ一度も使ったことがないのです。
先日に開催したkintone Café 神奈川でも懇親会でその話題が出て、次のお題はライトコースハックに決まりました。そのタイミングの良さもあって、山崎さんの登壇でボルテージが上がりました。

スタンダードコースに頼ってしまうのはシステム開発会社の弱み。
工夫次第では関数だけでやり切れる。

と言いつつ昇栄さんも、ついにスタンダードコースに舵を切られるそうです。
うーむ、私としては納得ができる結末。
ですが、ライトコースではやはり限界があるのか、という割り切れなさが残ります。

むしろライトコースを突き詰めて、そこからスタンダードコースに舵を切るのがkintoneを提案する身としては正しい在り方なのか。
そもそも、最初からスタンダードコースがありきで提案する弊社のやり方が正しいのか。
ライトコースを突き詰めたからこそ、スタンダードコースに上げる際に発生する費用を捻出するための不要な業務やサービスが抽出でき、社内の稟議も通りやすいのか。

私の中でもっとも考えさせられたのが山崎さんの登壇でした。
私もそうですから、山崎さんがkintoneを導入するにあたってのいきさつや苦労は皆さんにとって、興味津々のはず。

アンケートでもぜひkintone Café 神奈川で話してください、とむちゃぶりを書いてしまいました。
ぜひまた、お話を伺えればと思います。

山崎さん、ありがとうございました!


続いては有限会社光成工業 畠山 成光さんです。

それまでに五組の登壇を聞いて少々疲れ気味の観客に向かって、ハイテンションで登壇する畠山さん。「Let’s kinjoy!」の決めゼリフとポーズを武器に、会場の反応が薄くとも孤軍奮闘する姿に最初は若干の痛々しさを感じました。
が、それをものともせず、会場の空気を徐々に自分のものにしていく姿はまさにライブ!この会場の雰囲気が変わっていく熱が感じられるのがライブ会場の良さなのですね。これはオンラインでは体験できません。あらためて、来てよかったと思いました。
会場の聴衆を味方につけ、会場の雰囲気をライブで変えた畠山さんの打たれ強いメンタルとkintoneが大好きな熱量。
この熱さがあってこそ、光成工業さんは変わったのだと強く納得できました。そして、これは畠山さんが選ばれるのではないかと、登壇されている途中から感じました。

でも、聴衆の皆さんは決して畠山さんの「Let’s kinjoy!」の決めゼリフや熱量に幻惑されたわけではないのです。
実際、光成工業さんの取り組みは、参考になるべき点がとても多くありました。

まず、一部メンバーだけで動いて失敗した後、社長様から言われた「全員でやれ」の言葉。
早いうちから一部の方だけでやってしまい、実際に使う方に最後に伝えてしまうと、kintone導入は失敗はせずとも必ず苦労します。私も今までに何度か、失敗をやらかしたことがあります。

そして全員でやるようになってからの畠山さんの動きが素晴らしい。あさっての全体朝礼までに宣言するように、との指令を基に、告知動画を四人で作ってしまうのです。
しかもキックオフイベントではそれまで使っていた紙の日報の原本を現場のリーダーが破る姿を示す。その結果、日報のデジタルへの切り替えが一気に進んだそうです。


さらに、現場の年配の社員さんの声を生かした専用アプリ。これ、なかなかできるようでできないです。でも、それをやってしまったところが素晴らしい。
私たち導入側も、ここまで全ての社員さんを巻き込めた導入ができているのだろうか。すべての社員さんの声が聞けているのだろうか。プロジェクトメンバーだけで完結していないだろうか。
とても勉強になりました。

畠山さん、おめでとうございました!

東北・北海道地区代表には畠山さんが選ばれましたが、6組の皆さんの中で優劣があったのではなく、東北・北海道からの代表としてAWARDを勝ち取ってくれるのではないか、そんな期待があったからこその選出理由だったのでしょうね。


さて、投票結果の集計中は、サイボウズ東北支社の大越さんをファシリテーターとし、
社会保険労務士法人めぐみ事務所の原 和也さんと信幸プロテック株式会社村松 直子さんの鼎談です。
題して「スペシャルセッション「もっぺん、聞かせでけねが?おめほのきんとーん!」」

各お題が東北弁で書かれ、それを読み上げる大越さんの東北弁が流ちょうなのがよかった。

このマトリクスに出ているとおり、それぞれの導入経緯の違いが対比できているのがよかったです。

私も、こうと決めつけず、お客様の内部をよく把握し、お客様に適した提案をしていかなければ。学びが大きすぎます。

公平に。そして透明性をもって。
【kintoneは「楽しい」を大切に】 2023/4/13 kintone hive sendai2023 まとめ – Togetter


夜はアフターhive交流会。
今回、前日の米沢での商談に一緒にいった頼りになるパートナーさん二人と。


冒頭にすがわらさんと水沢さんによるhiveの振り返り。
この場で水沢さんからは弊社で副業も込みで働いていることをカミングアウトしていただきました。

今後とも東北を一緒に盛り上げていきましょう!

続いては、6班に分かれての業務改善ワーク。私もかつてこのワークはサイボウズさんのオフィスで取り組ませていただいたことがあります。それ以来、数年ぶりに模造紙と付箋とマーカーを駆使し、私の中で錆びついた学びを新たにしました。
私たちの班にいらっしゃった方がまさにkintone導入前。これからkintoneの社内提案に入られるそうです。同じ班の私たちにとってはkintone hiveで学んだ成果をお見せできる格好の場です。
学んですぐに実践。とても貴重な場となりました。

埼玉、東京、神奈川に帰らねばならない私たちは、二次会以降はご遠慮しました。
仙台駅から乗った新幹線では、今回のhiveでの学び。商談で出た課題やこれからの進め方など、存分に語り合えました。

商談をご一緒した郡山、米沢のみなさま。kintone hive sendaiの会場やアフターhive懇親会で出会った皆様、本当にありがとうございました!

そして充電器を託してしまった松井さん、次回どこかのhiveで必ずや!


ワーキングツリーにはkintoneとboxをお飾り!


kintone Advent Calendar 2019の24日目の記事です。

  Topへ↓

ん?この著者、この間もAdvent Calendarでみたで? はい。二度目の登場です。

kintoneは優れたツールですが完全ではない?
なーんてディスられても動じず、欠点を正直に認めるのもkintoneの憎めないところ。そう思ってやまない著者です。

kintoneの欠点のいくつかはすぐに挙げられます。
例えばブラウザーベースで動いているので、ファイルアップロードの作業が面倒、とか。
添付ファイルフィールドに画像データを放り込みまくると、一ユーザーあたり5GBの容量の制限が足かせになってくる、とか。

そんな限界を解消するためのささやかなクリスマスプレゼントを皆様にお届けしたいと思います。
なに、ちょっとした贈り物です。クリスマスツリーによくぶら下がっている箱のような。
箱・・・つまりboxです。
今回の記事では私の2019年の失敗事例も公開しているので、ひょっとしたら皆さまのご参考になるかもしれません。

box for kintoneのご紹介

  Topへ↑

世の中にオンラインストレージ製品はたくさんありますよね。その中でもboxが存在感を出しているのはご存じでしょうか。

kintoneとboxの連携はbox for kintoneというプラグインとして公開されています。
それを使えばブラウザー上でアップロードなどせず、ドラッグ&ドロップでブラウザー上から操作できちゃうのです。

クライアントツールのbox Driveをインストールすれば、Windowsのエクスプローラと同じ操作でbox上にファイルをアップロードできてしまう。なんて優れもの。

boxを使うと無尽蔵(契約プランによる)を誇る容量にファイルを置きまくり。
それをkintoneの画面上からに自由に呼び出せる。素晴らしい!
上に書いたkintoneの弱点を周囲のツールが補ってくれるいい例です。
本稿もそうしたkintoneを補ってくれる一つの例としてお役に立てれば幸いです。お日柄もよいので。

box for kintoneの使い方は、Cybozu developer networkにも出ています。
https://developer.cybozu.io/hc/ja/articles/205070124-Box-for-kintone その記事に従えば、簡単にbox for kintoneを導入できるはずです。

ところが、この記事で書かれているのは、一つのレコードに一つのフォルダーを対応させるところまで。
kintoneでちょっとしたシステムを作ろうとすれば複数アプリにまたがった構成が必要です。それに応じてboxのフォルダー構成も複数の階層にまたがってしまいます。

合同会社アクアビットダム設計なる会社

  Topへ↑

たとえば、大阪と東京に支店がある合同会社アクアビットダム設計があったとします。
この会社はダムを独自の技術で製造し、お客様にお納めしている設定です。

受注システムをkintoneで構築するにあたり、
大阪支店[組織]の
長井何某[個人]が担当する
担当案件[案件]の
施行状況[施工]と
湛水状況[湛水]を管理すると仮にしましょう(工程はしょりすぎ。ちなみに最後の工程は水を貯める工程です)。

他に顧客マスタがあるでしょうがここは割愛。また、[組織]と[個人]はアプリではなく、kintoneのアカウントを使用する想定です。
この場合3アプリですね。

ここでご注文からの流れをkintoneで管理したとしましょう。
各アプリの連動はkintoneのアクション機能を使ったとします。

ダム完成までにはさまざまな状況を報告していかねばなりません。するとダムの進捗に合わせて写真が大量に溜まっていきます。
kintoneの添付ファイルフィールドにファイルをアップしていると、すぐに容量が危うくなりかねません。
ここでboxの出番です。

ここでboxで写真を管理しようとした場合、box内のフォルダー構成はこのようになると思います。

さて、先ほどご紹介したbox for kintoneを思い出してみましょう。
プラグイン設定画面にルートフォルダーのIDを設定していましたね。

つまり、アプリ自体にルートフォルダーのみを作る仕様。
それって、どのレコードであろうと共通で1つのフォルダーだけ、、、
いやいや多層boxと多層アプリでは対応できないのはちょっと、、、
結論! box for kintoneだとちょっとキツイかも。

合同会社アクアビットダム設計にboxを

  Topへ↑

ということで、本稿では多段階にわたるboxの連動例をお伝えしたいと思います。また、その時にしでかしてしまった失敗と、そのリカバリ例もお伝えしたいと思います。

まず、話を簡単にするため、合同会社アクアビットダム設計としてのルートフォルダーを設定しておきましょう。

さらに、支店ごとにフォルダーを設定し、支店の配下に担当ごとのフォルダーも生成しておくと話が早いですね。

実際のboxのフォルダー構成はこんな感じ。

ここでルートフォルダーのフォルダーIDを取得しておきます。boxの画面から取れます。

その状態で、案件アプリに新規レコードを登録します。
案件アプリの項目には案件の主管支店と、案件の主担当を指定するフィールドも忘れずに。もちろん必須項目として。

なぜ必須項目にするのでしょう。
その理由は、レコードが保存成功後、案件フォルダーを作る際にどこのフォルダーの配下に作成するか決めなければならないためです。

boxのフォルダー生成APIについて

  Topへ↑

ここでboxの仕様を押さえておきましょうか。
サービスの仕様を確認するには、APIから逆引きしたほうが理解しやすい。いわゆる技術者あるあるです。
boxのAPIはこちらのサイトをご覧になると良いでしょう。
https://ja.developer.box.com ・・developerサイトトップ
https://ja.developer.box.com/reference ・・APIレファレンス

boxのフォルダー作成の項を読むと、親であるフォルダーのIDがパラメーターとして必須のようです。
編集時には親フォルダーのIDは必須ではなくなりますが、もしフォルダーの場所を移動する際は親フォルダーのIDは指定しなければなりません。

案件フォルダーを作る際は、親となる担当者フォルダーのIDを把握しておかねばなりません。
そしてその上の支店フォルダーも。

つまり、案件レコードの保存のタイミングで行うべきことは、まず、そのレコードの支店フィールドの値に等しい支店フォルダーを検索することです。
その際、基準となるのはルートフォルダーです。

ルートフォルダーの下にある支店フォルダーを検索し、そのIDを特定します。
間髪入れずに支店フォルダーの配下にある担当者フォルダーを検索します。
これは同一担当者が複数支店にフォルダーを持っている場合など、運用も考慮していますが、支店フォルダーのIDを内部で保持できるのであれば、いきなり担当者フォルダーから検索してもよいです。
重要なのは案件フォルダーを作成するにはその親フォルダーのIDを事前に必ず保持しておくことです。

先ほど、kintoneの案件アプリの支店と担当者の両フィールドは必須でなければならないとしたのには、そういう理由があったのです。
これら二つのフィールドの値がないと、案件を保存する際に生成されるべき案件フォルダーの保存先が迷子になってしまうので。

JavaScriptで実装してみた

  Topへ↑

続いてはいよいよboxの操作を行います。

その前に本稿ではboxの権限周りには踏み込まないことを言っておきます。
OAuthについては、もともとbox  for  kintoneで用意されていたclient IDを使用します。本当はbox内でアプリを作成し、そのアプリ内で設定した権限を認証しなければならないのですが。
box for kintoneに甘えてしまいましょう。

ついでにpromise処理が考慮されたAPI実行部分もbox for kintoneの処理を流用させていただきましょう。

処理の大まかな順序としては以下の通りです。
ただ、のちに述べますが、このコードは動きません。なのでコードは画像として参考程度に載せます。

まず、イベントが動くタイミングはapp.record.create.submit.successです。新規作成処理成功後ですね。

処理の都合上、この中で別のアプリに更新を行い、その結果が成功した場合にboxフォルダー生成処理を呼び出しています。

boxフォルダー生成処理では、まずルートフォルダーから支店フォルダーを検索します。
続いて支店フォルダーから担当者フォルダーを検索します。

ここでboxの検索の仕様が立ちふさがってきます。
boxの検索仕様として、対象の種類、生成時刻、オーナーIDや親フォルダーIDなどは指定できるのですが、肝心の文字列を完全一致で検索できないのです。queryというパラメータがあるにもかかわらず、そこに指定した文字列は曖昧検索として処理されてしまうのです。
APIレファレンス

つまり、親フォルダーに属する検索対象が複数ありうる場合、検索文字列に工夫が必要です。例えば姓名の間にスペースが入る場合など。
「長井 権兵衛」と「長井 主水」が対象のフォルダー配下にあって「長井 権兵衛」を検索したい場合、queryに「長井 権兵衛」を設定してもマッチしません。
ではどうやればよいか。
スペースの前後の文字列で検索するのです。
この場合、「長井」または「権兵衛」で検索します。すると前者は二件がヒットし、後者は一件がヒットします。
その結果を再度ループして回し、一件ごとにname属性の値が検索文字列に一致するかを確認する。
そのような面倒な処理がboxの検索には必要です。

このコードも実際は使っていませんが、軽く提示します。

これで、担当者フォルダーIDまで求められました。

boxのフォルダー生成と検索にまつわる問題

  Topへ↑

続いてはフォルダーの生成に移りましょう!
APIレファレンス

生成にあたっては、名前と親フォルダーのIDを指定するだけです。

これで、案件レコードが保存されたら案件フォルダーを作成するところまでができました。

ここで当初想定していたboxの構成を見てみましょう。
案件フォルダーの配下に「提案状況」「施工状況」「湛水状況」の三フォルダーがあります。
このフォルダーの生成にも実は厄介な問題が潜んでいます。

例えば、案件のレコードが保存されました。そして案件フォルダーが生成されました。
そしたら、アクション機能によって施工状況アプリにレコードをコピーし、施工状況アプリでもレコードが保存された瞬間、案件レコードの時と同じように施工状況フォルダーを生成すればええんちゃうの?と思ったでしょう。

ところが、フォルダーを生成するには親のフォルダーの指定が必須です。
親フォルダー、つまり案件フォルダーをフォルダー生成処理の直前で検索してフォルダーIDを取得しなければなりません。
ところがこの親フォルダーの検索取得にはひとつハードルが控えています。そのハードルとは、コンテンツが生成されてから検索可能となるまでに時間がかかる、というものです。
boxはなんらかのコンテンツが作成されてから、それが検索可能となるまでにbox内部でindexを構築しており、それに時間が掛かるのです。
boxの APIレファレンスには以下のように書かれています。

つまり、案件フォルダーの生成からすぐ、施工状況アプリのレコードを保存した場合、親となるべきフォルダーが検索できないため、親フォルダーの指定ができないのです。

boxを多層構造でkintoneと連動させる場合、この仕様上の制限は現状では避けられません。

この制限を回避するため、発想を切り替えました。
つまり、案件フォルダーが生成された後、同時に配下のフォルダーも作ってしまうのです。

box APIでは、フォルダー生成が成功した時点で返り値として生成されたフォルダーのIDが得られます。このIDを使えば配下のフォルダーも即時に生成できます。

このコードも実際は使っていませんが、軽く提示します。

この下の処理ではさらに生成した案件フォルダーのURLを取得し、そのURLやフォルダーIDをkintoneの2アプリに更新して設定しています。

ここまででkintoneのapp.record.create.submit.successイベントを見てきました。その結果、実装ができそうです。
テストでもフォルダーが意図通りに生成されました。開発用のPCでも、お客様のご担当者様のPCでも。

バグ大魔王降臨!

  Topへ↑

ところが! やったと思った安心のかげに潜むのが落とし穴。バグが出てしまったのです。
テストではうまく動いていたのに、いざ本番になるとうまくいかない。なんということでしょう!

実は、その根本的な原因は今もなお究明できていません。
事象としてはboxにAPIリクエストを投げた後、何も戻ってこないのにプログラムが終了してしまいます。httpレスポンスすら帰ってこずに。
それも終了する場所がまちまちなのが始末が悪い。複雑なPromiseの構造に加え、referredを混在させたことにも問題があったのかもしれません。
この不具合がやっかいなのは、boxからのレスポンスを待つ間、app.record.create.submit.successの結果が完了できないことにあります。その間、ブラウザーは固まってしまい、kintoneを利用されている皆様にはただ困惑が。

そして、この不具合の原因がブラウザーにあるのか、box側にあるのか、kintone内部にあるのか、それともPCのスペックにあるのか。はたまたネットワーク環境によるものなのか。いまだに分っていません。
ただ、ブラウザー上でレスポンスを待つ運用はまずい、という悔いだけは骨身に沁みました。
私はその原因を追究するよりもお客様の運用を円滑に進めることを優先しました。
その決断として、ブラウザーに依存する実装を止めました。

AWSへ処理を移管

  Topへ↑

では、どうすればよいか。

幸いなことにkintoneにはWebhookという機能が備わっています。Webhookには、レコード保存時にWebhookのリクエストを受け付けてくれるWebhook URLを設定できます。

私がWebhook URLとして設定したのはAWSのAPI Gatewayで設定したURLでした。
API Gatewayについての説明は割愛しますが、kintoneから受け取ったWebhookのリクエストに含まれるJSONを読み取り、それを後続の処理に渡すことができます。
後続の処理にはAWS Lambdaを選びましたので、同じAWS上で処理が連携できます。

AWS LambdaではNode.jsを使い、ほぼkintoneのkintone.app.create.submit.successで実装したのに近いコーディングを行いました。
box Node SDKがAWS Lambdaから簡単に使用できるので、それを使えば似たような実装ができるのです。
ただし、boxのアプリは一から作る必要があります。設定もあれこれ行う必要が生じました。
最初、こちらのブログの力も借りました。ありがとうございました。
Lambda関数のコードを以下に掲示します。なお、このコードは動いているものを基にいろいろといじっているので参考になると思います。

/**
 * This sample demonstrates how to call Box APIs from a Lambda function using the Box Node SDK.
 *
 * For step-by-step instructions on how to create and authorize a Box application,
 * see https://github.com/box/samples/tree/master/box-node-lambda-sample.
 */
const BoxSDK = require('box-node-sdk');                                                // Node.jsのbox-node-sdkモジュールを呼び出す
const request = require('request');                                                    // Node.jsのrequestモジュールを呼び出す
const boxConfig = JSON.parse(process.env.BOX_CONFIG);                                  // AWS Lambdaの環境変数のBOX_CONFIGの値をJSONで扱えるように

boxConfig.boxAppSettings.appAuth.keyID = boxConfig.boxAppSettings.appAuth.publicKeyID; // 9行目で取り出したkeyIDにpublicKeyIDを代入

const sdk = new BoxSDK(boxConfig.boxAppSettings);                                      // 9行目で取り出したboxAppSettingsをsdkに代入

/**
 * Create a service account client that performs actions in the context of the specified
 * enterprise.  The app has a unique service account in each enterprise that authorizes the app.
 * The service account contains any app-specific content for that enterprise.
 * Depending on the scopes selected, it can also create and manage app users or managed users
 * in that enterprise.
 *
 * The client will automatically create and refresh the service account access token, as needed.
 */
const client = sdk.getAppAuthClient('enterprise', boxConfig.enterpriseID);             // boxアプリが適用できるアカウントのグローバル設定を管理

var DOMAIN = '*********.cybozu.com'; //kintone環境のドメイン                            // *****はご使用のkintoneのサブドメインを
var APP_ID_1287 = 1287;   //案件管理アプリのアプリID
var BASE_URL = "https://" + DOMAIN + '/k/v1/';
var APITOKEN_1287 =  "kintoonkaramottekitatookunwokokoniiretene";                      // kintoneの案件アプリのAPIトークン
var headers_1287 = {'X-Cybozu-API-Token': APITOKEN_1287};                              // リクエストで使用するヘッダ
var FolderId;
var updaterecordid_1287;

exports.handler = (event, context, callback) => {                                      // eventはkintoneのWebhookからAPI Gatewayを経由したレコード情報
                                                                                       // contextはLambda関数に関する情報
    const API_BASE_PATH = 'https://api.box.com/2.0';                                   // box Node SDKの文法に準拠

    // targetnameはコンテンツの文字列
    // typeはコンテンツの対象。本稿の場合はfolder
    // content_typesは検索対象とするプロパティ。本稿の場合はname
    // limitは検索結果として戻す件数。
    // idsは親フォルダーのフォルダーID
    // methodは本稿では全てGETなので使用していない
    // dataは本稿の場合検索対象(支店,担当者,案件No)のうち、担当者の場合["担当名"]で渡ってくる。
    function searchFolder(targetname, type, content_types, limit, ids, method, data, success, error) {  //157,159,161行目から呼び出されて検索処理を実施
        if (data !== undefined) {                                 // dataが指定されている場合
            if (data[0] === "担当名") {                            // dataの配列の最初の要素が"担当名"の場合
                targetname = targetname.split(' ')[0];           // 受け取るtargetnameは「長井 権兵衛」の様に全角スペースで区切られた姓名なので姓を取得
            }
        }

        return new Promise(function (resolve, reject) {           // Promiseを設定
            client.search.query(                                  // 24行目でclientとして承認されたbox Node SDKのsearchクラスのquery関数を呼び出し
                "\"" + targetname + "\"",                         // 最初のパラメーターは検索対象文字列。文字列なのでエスケープした""で囲む。でも曖昧検索
                {                                                 
                    fields: 'id,name,modified_at,extension,permissions,collections',  //検索結果として返すコンテンツのプロパティ
                    type: type,                                                       //folder
                    content_types: content_types,                                     //検索対象はnameプロパティ
                    limit: limit,                                                     //結果として返す件数
                    ancestor_folder_ids: ids,                                         //親フォルダーID 
                    offset: 0                                                         //オフセットしないので0
                })
                .then(function(results){                                              //結果が取得されたのでこのPromiseチェーンへ
                    if (data !== undefined) {                                         //dataが指定されている場合
                        if (data[0] === "担当名") {                                   //dataの配列の最初の要素が"担当名"の場合
                            for (var i = 0; i < results.entries.length; i++) {        //戻り値の件数分(limitで指定した件数分)
                                if (results.entries[i].name === data[1]) {            //戻り値のnameプロパティがdataの2番目の要素(担当名)か
                                    resolve(results.entries[i].id);                   //Promiseは完了したと戻り値のidプロパティ(フォルダーID)を返す
                                }
                            }
                        }
                    } else {
                        resolve(results.entries[0].id);                               //Promiseは完了したと戻り値のidプロパティ(フォルダーID)を返す
                    }
                })
                .catch(function(error){ // エラーの場合
                    reject(error);
                });
        });
    }

    // createParamは生成フォルダー名と親フォルダーIDが含まれたJSONオブジェクト
    function postFolder(createParam) {                     //176行目から呼び出されてフォルダー生成処理を実施
        return new Promise(function (resolve, reject) {    // Promiseを設定
            client.folders.create(createParam.parent.id, createParam.name)  //24行目でclientとして承認されたbox Node SDKのfolderクラスのcreate関数を呼出
                                                                            //1つ目は親フォルダーID、2つ目は生成するフォルダーの名称 
                .then(function(results){                                    //85行目の処理が成功したのでこのPromiseチェーンへ
                    var ankenid = results.id;                               //生成したフォルダーIDを以下のforeach内で使うためにankenidに代入 
                    var subfolders = [                                      //生成した案件フォルダーの配下に作成する三つのフォルダー名を配列にしています
                        "提案資料",
                        "施工状況",
                        "湛水状況"
                    ];

                    var promiseset = [];                                    //三つのフォルダーの生成が終わるまで待つPromiseを三つ作るので配列を設定
                    subfolders.forEach(function(val,index,ar){              //89行目で生成した配列の各要素をループします
                        promiseset[index] = new Promise( function( resolve, reject ) {  //95行目で生成した配列にPromiseを設定します。
                            client.folders.create(ankenid, val)             //24行目でclientとして承認されたbox Node SDKのfolderクラスのcreate関数を呼出 
                                                                            //1つ目は親フォルダーID(案件フォルダー)、2つ目は生成するサブフォルダーの名称
                                .then(function(results){                    //98行目の処理が成功したのでこのPromiseチェーンへ
                                    resolve(results.id);                    //97行目のPromiseは完了したと戻り値のidプロパティ(フォルダーID)を返す
                                }).catch(function(error){                   //98行目の処理が失敗したのでこのPromiseチェーンへ
                                    reject(error);                          //97行目のPromiseは失敗したとエラーオブジェクトを返す
                                });
                        });
                    });
                    Promise.all( promiseset )                               //97行目で設定した三つのPromiseが全て完了したらここに来る
                        .then( function ( message ) {
                        resolve(ankenid);                                   //84行目のPromiseは完了したと戻り値のidプロパティ(フォルダーID)を返す
                    })
                        .catch( function ( reason ) {                       //97行目で設定した三つのPromiseのどれかが失敗したらここに来る
                            console.log( reason ) ; // "失敗!!"
                        reject(false);                                      //84行目のPromiseは失敗したとエラーオブジェクトを返す
                    });
                })
                .catch(function(error){                                     //85行目の処理は失敗したらここに来る
                    reject(error);                                          //84行目のPromiseは失敗したとエラーオブジェクトを返す
                });
        });
    }

    // boxフォルダーIDは更新対象となるフォルダーID
    // createParamは更新フォルダー名と親フォルダーIDが含まれたJSONオブジェクト
    function putFolder(boxフォルダーID, updateParam) {             //165行目から呼び出されてフォルダー更新処理を実施
        return new Promise(function (resolve, reject) {         // Promiseを設定
            client.folders.update(boxフォルダーID, updateParam)    //24行目でclientとして承認されたbox Node SDKのfolderクラスのupdate関数を呼出
                                                                //1つ目は対象となるフォルダーID、2つ目は更新するフォルダー情報の含まれたJSONオブジェクト 
                .then(function(results){                        //126行目の処理が成功したのでこのPromiseチェーンへ
                    resolve(results.id);                        //125行目のPromiseは完了したと戻り値のidプロパティ(フォルダーID)を返す
                })
                .catch(function(error){                         //126行目の処理が失敗したのでこのPromiseチェーンへ
                    reject(error);                              //125行目のPromiseは失敗したとエラーオブジェクトを返す
                });
        });
    }

    function getFolderURL(createdid) {                          //178行目から呼び出されてフォルダーの共有処理を実施
        return new Promise(function (resolve, reject) {         // Promiseを設定
            client.folders.update(createdid, {shared_link: client.accessLevels.OPEN}) 
                                                                //24行目でclientとして承認されたbox Node SDKのfolderクラスのupdate関数を呼出
                                                                //1つ目は対象となるフォルダーID、2つ目は更新するフォルダーのプロパティ(共有設定)
                .then(function(results){                        //139行目の処理が成功したのでこのPromiseチェーンへ
                    resolve(results.shared_link.url);           //138行目のPromiseは完了したと戻り値の共有URLプロパティ(リンクURL)を返す
                })
                .catch(function(error){                         //139行目の処理が失敗したのでこのPromiseチェーンへ
                    reject(error);                              //138行目のPromiseは失敗したとエラーオブジェクトを返す
                });
        });
    }
    function createBoxFolder(支店, 担当者, 案件No, boxフォルダーID) {  //212行目から呼び出されてフォルダーの共有処理を実施
        return new Promise(function (resolve,reject) {             // Promiseを設定
            var rootfolder = "12345678910";                        //boxのフォルダー制御のルートとなるフォルダーのフォルダーIDを静的に代入
            var ownerbranchfolder;                                 //支店フォルダーのフォルダーID
            var personinchargefolder;                              //担当者フォルダーのフォルダーID
            var createParam;                                       //searchFolder関数へはダミーオブジェクト。putfolderとpostfolderへはJSONオブジェクト

            searchFolder(支店, "folder", "name", 10, rootfolder, 'GET', createParam).then(function (branchfolderid) {  //45行目へ
                ownerbranchfolder = branchfolderid;                           //searchFolderからの返り値を上位スコープのownerbranchfolderへ代入
                searchFolder(担当者, "folder", "name", 10, ownerbranchfolder, 'GET', ["担当名",担当者]).then(function (personfolderid) {  //45行目へ
                    personinchargefolder = personfolderid;                    //searchFolderからの返り値を上位スコープのpersoninchargefolderへ代入
                    searchFolder(案件No, "folder", "name", 10, personinchargefolder, 'GET', createParam).then(function (projectfolderid) {  //45行目へ
                        var name = "案件No" + " " + 案件No;                    //生成/更新する案件フォルダーの名称を設定する
                        createParam = {name: name, parent: {id: personinchargefolder}};  //案件フォルダーの設定情報をJSONオブジェクトに組み立てる
                        if (projectfolderid.length > 0) {                     //161行目で案件フォルダーが存在した場合(フォルダー情報更新)
                            putFolder(projectfolderid, createParam).then(function (updatedid) {  //124行目へ
                                FolderId = updatedid;                         //161行目の処理で得た更新したフォルダーIDをスコープ外の168行で使うため
                                getFolderURL(updatedid).then(function (updatedurl) {             //137行目へ
                                    resolve(FolderId+"****"+updatedurl);      //151行目のPromise完了をフォルダーIDと共有URLプロパティ(リンクURL)で返す
                                }).catch(function(error){                     //167行目の処理が失敗したのでこのPromiseチェーンへ
                                    reject(error);                            //151行目のPromiseは失敗したとエラーオブジェクトを返す
                                });
                            }).catch(function(error){                         //165行目の処理が失敗したのでこのPromiseチェーンへ
                                reject(error);                                //151行目のPromiseは失敗したとエラーオブジェクトを返す
                            });
                        } else {
                            postFolder(createParam).then(function (createdid) {       //83行目へ
                                FolderId = createdid;                                 //生成したフォルダーIDを以下の179行目で使うためにFolderIdに代入
                                getFolderURL(createdid).then(function (createdurl) {  //137行目へ
                                    resolve(FolderId+"****"+createdurl);      //151行目のPromise完了をフォルダーIDと共有URLプロパティ(リンクURL)で返す
                                }).catch(function(error){                             //178行目の処理が失敗したのでこのPromiseチェーンへ
                                    reject(error);                                    //151行目のPromiseは失敗したとエラーオブジェクトを返す
                                });
                            }, function(res) {                                        //176行目のフォルダー生成処理でrejectレスポンスが返った場合
                                if (res.status && res.status === 409) {               //176行目のフォルダー生成処理でrejectレスポンスが409返った場合
                                    if (res.context_info                              //176行目のフォルダー生成処理でrejectレスポンスが競合を示した場合
                                        && res.context_info.conflicts
                                        && res.context_info.conflicts.length > 0) {
                                        return;                                       //150行目のcreateBoxFolder関数を終える
                                    }
                                }
                            }).catch(function(error){                                 //176行目のフォルダー生成処理でエラーが帰った場合
                                reject(error);                                        //151行目のPromiseは失敗したとエラーオブジェクトを返す
                            });
                        }
                    }).catch(function (error) {                                       //161行目のフォルダー検索処理でエラーが帰った場合
                        // 非同期処理失敗。呼ばれない
                        console.log(error);
                    });
                }).catch(function (error) {                                           //159行目のフォルダー検索処理でエラーが帰った場合
                    // 非同期処理失敗。呼ばれない
                    console.log(error);
                });
            }).catch(function (error) {                                               //157行目のフォルダー検索処理でエラーが帰った場合
                // 非同期処理失敗。呼ばれない
                console.log(error);
            });
        });
    }

    var recordjson = JSON.parse(event.body);                                 //34行目で受け取ったkintoneのWebhookのレコード情報をJSON形式で扱えるように
    updaterecordid_1287 = recordjson.record.レコード番号.value;               //210行目のレコードデータの「レコード番号」フィールドの値を代入
    createBoxFolder(recordjson.record.支店.value[0].code,                    //150行目へ
                    recordjson.record.担当者.value, 
                    recordjson.record.案件No.value, 
                    recordjson.record.boxフォルダーID.value).then(function(idurl) {
        if (idurl) {                               //212行目のcreateBoxFolderの戻り値(168、179行目で値設定)
            var targetrecordids = [updaterecordid_1287+"**"+APP_ID_1287];   //211行目で設定したレコード番号と27行目で設定したアプリID
            var kintonepromiseset = [];                                     //kintoneのレコードアップデートが終わるまで待つPromiseの配列を設定
            targetrecordids.forEach(function(val,index,ar){                 //217行目で生成した配列の各要素(本稿では1つ)をループします
                kintonepromiseset[index] = new Promise( function( resolve, reject ) {  //218行目で生成した配列にPromiseを設定します。
                    var body_post = {                                                  //kintoneの既存案件アプリを更新するレコードを組み立てます。
                        app: val.split("**")[1],                                       //217行目で設定した配列の**で区切られた右側(アプリID)
                        id: val.split("**")[0],                                        //217行目で設定した配列の**で区切られた左側(レコード番号)
                        record: {
                            boxフォルダーID: {
                                value: idurl.split("****")[0]                       //212行目のcreateBoxFolderの戻り値の****で区切られた左のフォルダーID
                            },
                            表示: {
                                value: idurl.split("****")[1].replace("*******.box.com","app.box.com")
                                         //212行目のcreateBoxFolderの戻り値の****で区切られた右のURL(契約のboxのサブドメインをapp.box.comに置換の必要あり)
                            }
                        }
                    };
                    var options_getsalesamount = {                            //リクエストのbody部分を組み立てます。
                        url: BASE_URL + 'record.json',                        //28行目で設定したURLのルートと一行レコードの更新なのでrecord.jsonを連結
                        method: 'PUT',                                        //更新なのでPUT
                        headers: headers_1287,                                //30行目で設定したAPIトークン
                        'Content-Type': 'application/json',                   //リクエストのボディ部分のタイプ
                        json: body_post                                       //221行目で設定したボディ部分
                    }
                    //レコードを取得
                    request(options_getsalesamount, function (error, response, body) {    //Node.jsのrequestモジュールで234行のリクエストを送信
                        if (error) {                                                      //242行目の値がerrorだったら
                            console.log('Error: ' + error.message);
                            reject();                                                     //220行目のPromiseは失敗したとエラーオブジェクトを返す
                        }
                        console.log("kintone recordput:succcess"+val);
                        resolve();                                                        //220行目のPromise完了を返す
                    });
                });
            });
            Promise.all( kintonepromiseset )                                              //220行目で設定したPromiseが全て完了したらここに来る(本稿は1つ)
                .then( function ( message ) {                                             //252行目の処理が成功したのでこのPromiseチェーンへ
                    context.done(null, {text: "kintone POST and Box Folder Create success!"});  //Lambdaの処理結果をログとして残す
            })
                .catch( function ( reason ) {
                    context.done(null, {text: "Box Folder Create failed!"});              //Lambdaの処理結果としてエラーログ
                return;
            });
        } else {
            context.done(null, {text: "Box Folder Create failed!"});                      //Lambdaの処理結果としてエラーログ
        }
    }, function(res) {                                                                    //212行目の返り値がrejectで戻ってきた場合
        context.done(null, {text: "Box Folder Create failed!"});                          //Lambdaの処理結果としてエラーログ
        return false;                                                                     //212行目の結果としてfalseを返す
    });
};

 

なんとか実装

  Topへ↑

いずれにせよ、私が2019年に出した唯一の大きなバグがこれでした。
結局、バグが出てから実運用にこぎつけるまでにさらに二カ月ほどの時間をいただきました。お客様にも多大なご迷惑をおかけしてしまいました。

これが実装できたことで、案件アプリにレコードを登録した時点で、Webhookが発動し、AWS API GatewayからAWS Lambdaを介してboxへのフォルダー生成と、レコードに対応するboxのURLとフォルダー番号をkintoneの該当レコードに登録することができました。

kintoneの画面上にboxのフォルダーを出す部分はbox for kintoneの内部にも書かれている通りです。
実際それを使わせていただいています。ありがとうございます。
以下にコードを載せていますが、疲れてきたのでコード内のコメントは割愛します。ごめんなさい。

(function() {
    'use strict';

    var BOX_CLIENT_ID = 'wkgp4k64whsha8mwvg7k5k63cim82mmv';   //sample_plugin_default
    // localStorage
    var LOCAL_STORAGE_PREFIX = 'kintone.plugin.' + BOX_CLIENT_ID;
    var LOCAL_STORAGE_JUDGED_ALLOW_ACCESS = LOCAL_STORAGE_PREFIX + '.judgedAllowAccess';

    var config = [];

    var BOX_EMBED_WIDTH = 840;
    var BOX_EMBED_HEIGHT = 420;

    var getUrl = function(path) {
        var matchedGuestSpacePath = location.pathname.match(/^\/k\/(guest\/\d+\/)/);
        var guestSpacePath = '';
        if (matchedGuestSpacePath !== null && matchedGuestSpacePath.length === 2) {
            guestSpacePath = matchedGuestSpacePath[1]; // "guest//"
        }
        var apiPath = '/k/' + guestSpacePath + path;
        return apiPath;
    };

    var boxApi = {
        clientInfo: {'provider': 'box', 'client': BOX_CLIENT_ID},

        getAccessToken: function() {
            // add a hash parameter for distinguishing OAuth redirect
            var delimiter = (location.hash.indexOf('#') === 0) ? '&' : '#';
            location.hash += delimiter + BOX_CLIENT_ID + '.oauth_redirect=true';
            kintone.oauth.redirectToAuthenticate(this.clientInfo, location.href);
        },
        hasAccessToken: function() {
            return kintone.oauth.hasAccessToken(boxApi.clientInfo);
        }
    };

    var validateConfig = function(record) {
        config['folderId'] = '0';//Box親フォルダーID
        config['keyFld'] = '顧客名';//kintoneキーフィールド
        config['boxUrl'] = '表示';//Box共有リンクの格納先
        config['boxFolderId'] = "boxフォルダーID";
        config['access'] = 'Open';//Box共有リンクのアクセス権[Collaborator/Company/Open]
        config['prohibitToDownload'] = 'false';//コラボレータにのみダウンロードを許可する

        if (!config) {return false; }
        return true;
    };

    var decorateBoxLinkField = function(boxUrl) {

        var boxLinkPattern = /^https:\/\/([a-zA-Z0-9]+).box.(com|net)(\/s\/[a-z0-9]+)$/;
        var match = boxUrl.match(boxLinkPattern);
        if (!match) {
            return;
        }
        var iframeSrc =
            'https://app.box.com/embed_widget/000000000000' +
            match[3] +
            '?theme=gray' +
            '&show_parent_path=no' +
            '&show_item_feed_actions=no' +
            '&partner_id=233';

        var elEmbed = kintone.app.record.getFieldElement(config.boxUrl);
        if (elEmbed === null) {return; }
        $(elEmbed).empty();

        var width = BOX_EMBED_WIDTH;
        var height = BOX_EMBED_HEIGHT;

        $(elEmbed).parent().css({
            'width': (width + 100) + 'px',
            'height': 'auto',
            'background-color': 'rgba( 255, 255, 255, 0 )'
        });
        var embedIframe = $('', {
            src: iframeSrc,
            width: width,
            height: height,
            frameborder: '0',
            allowfullscreen: 'true',
            allowscriptaccess: 'always'
        });
        $(elEmbed).append(embedIframe);
    };

    var judgedAllowAccessFlag = {
        isSet: function() {
            return (localStorage.getItem(LOCAL_STORAGE_JUDGED_ALLOW_ACCESS) !== null);
        },

        set: function() {
            localStorage.setItem(LOCAL_STORAGE_JUDGED_ALLOW_ACCESS, 'true');
        },

        remove: function() {
            localStorage.removeItem(LOCAL_STORAGE_JUDGED_ALLOW_ACCESS);
        }
    };

    kintone.events.on('app.record.detail.show', function(e) {
        if (validateConfig(e.record)) {
            var boxUrl = e.record[config.boxUrl].value;
            if (!e.record[config.boxUrl].value) {

                var elEmbed = kintone.app.record.getFieldElement(config.boxUrl);
                if (elEmbed === null) {return null; }
                $(elEmbed).empty();

            } else {
                decorateBoxLinkField(boxUrl);
            }
        }

        return e;
    });

    var checkAccessToken = function() {
        var oauth_redirect_param = BOX_CLIENT_ID + '.oauth_redirect=true';
        if (location.hash.indexOf(oauth_redirect_param) !== -1) {
            judgedAllowAccessFlag.set();

            // remove a hash parameter
            location.hash = location.hash.replace(oauth_redirect_param, '');

            var t = setInterval(function() {
                if (location.hash.indexOf(oauth_redirect_param) !== -1) {
                    // cancel button was clicked
                    clearInterval(t);
                    location.href = getUrl(kintone.app.getId() + '/');
                }
            }, 500);
        } else if (!judgedAllowAccessFlag.isSet() || !boxApi.hasAccessToken()) {
            kintone.oauth.clearAccessToken(boxApi.clientInfo, function(body, status, headers) {
                boxApi.getAccessToken();
                return null;
            });
        }
    };

    kintone.events.on('app.record.create.show', function(e) {
        if (validateConfig(e.record)) {
            checkAccessToken();
            e.record[config.boxUrl]['disabled'] = true;
            e.record[config.boxFolderId]['disabled'] = true;
        }

        return e;
    });

    kintone.events.on('app.record.edit.show', function(e) {
        if (validateConfig(e.record)) {
            if (!e.record[config.boxUrl].value) {
                checkAccessToken();
            } else {
//                e.record[config.keyFld]['disabled'] = true;
                e.record[config.boxFolderId]['disabled'] = true;
            }
            e.record[config.boxUrl]['disabled'] = true;
        }
        return e;
    });

    kintone.events.on('app.record.index.edit.show', function(e) {
        if (validateConfig(e.record)) {
            e.record[config.boxUrl]['disabled'] = true;
            e.record[config.keyFld]['disabled'] = true;
            e.record[config.boxFolderId]['disabled'] = true;
        }
        return e;
    });
})();

 

 

まとめ

  Topへ↑

実案件ではさらに凝った実装(フォルダー数も階層も本稿の例よりさらに多い)が施されています。
そして、古くboxが設定されていないレコードには手作業がたまに発生しているものの、実運用に乗っています。
この記事ではそれ以上の情報を出すことはお客様の業務に関わるのでここまでにしとうございます。

本稿がkintoneを運用している皆様にとって少しの手助けになれば幸せです。

kintone上で大量の添付ファイルに困っていらっしゃる方や、社内ファイルサーバーからの移行でお困りの方。他のPaaSからkintoneへ移行する作業があって、添付ファイルの扱いにお困りの方。
弊社では本稿のようなboxとkintoneの連動事例を何例も手掛けております。お困りの際はおっしゃってくださいませ。

最後に蛇足ですが、boxの案件で例に挙げた三つのダムは、私が実際に訪れてダムカードを入手した場所です。


当エントリーの参考にさせていただいたブログ

  Topへ↑

最後になりましたが、このエントリー作成にあたり、以下の2サイトからの情報を参考にさせていただきました。ありがとうございました。

 box APIレファレンス
 AWS Lambda上でBox Node SDKを利用する-九龍堂雑録


コーチングのグラフってkintoneで出せるんやって!


kintone2 Advent Calendar 2019の5日目の記事です。

  Topへ↓

突然ですが皆さん、コーチングって聞いたことがありますか?
あっ! そこのあなた、ページはそのままに!
これは間違いなくkintone Advent Calendarの記事ですから。
ほら!

きとみちゃん楽しいですよね!
https://kintone.cybozu.co.jp/jp/kitomi/

日々、お仕事に励むきとみちゃん。
きとみちゃんとお仕事をする仲間はとっても個性が豊か。

ちょっぴりあわてんぼうでドジっ子のきとみちゃんがkintoneに救われる姿は微笑ましいです。
ちなみに私は巻物で見積書を出してくださる麻呂な方が好きです。この方のお名前はなんでおじゃる?

さて、きとみちゃんがお仕事をする上で助けになる手法はkintoneの他にもさまざまなものがあります。

その中の一つが冒頭に書いたコーチングなのです。

コーチングを一言で言い表すなら、
・相手の学習や成長、変化を促し、相手の潜在能力を解放させ、最大限に力を発揮させる。
でしょうか。

詳しくはWikipediaの「コーチング」
をご覧くださいませ。

ビジネスにフォーカスを当てたコーチングの歴史はまだまだ浅いです。
ここでお伝えしておかなければならないのは、自己啓発セミナーとは違う、ということです。

と、偉そうにウンチクを述べる私ですが、コーチングを受けた経験は人生で1,2回だけ。
では、そんな私がkintone Advent Calendarで何を語るというのでしょうか。

結論を先に書いちゃうと、kintoneでこんなグラフを作ってみましょう!
ということなんですね。

グラフとデータのご説明

  Topへ↑

上に登場したのは四つの傾向を円グラフにしたものです。
それぞれの傾向の文字列にマウスを合わせると、事前に登録しておいたキーワードが出てくる。
これ、実は以前、お客様に依頼されて作ったkintoneにChart.jsを組み込んだグラフ生成の仕掛けです。

私はコーチングには無知です。
ですから、kintoneに入力画面を作り、その結果を集計することで、設問に応じた四つの傾向が算出できる、ということを知ったときは新鮮でした。

お客様によれば、
相手をほめる場合の、個人に響くキーワードは4つの傾向に分けられる
だそうです。

それに合わせて、こんな入力画面を作ってみました。

仮に20問の設問としています。それぞれの4つの傾向ごとに5問を設問しました。
それぞれの問いごとに
・よく当てはまる
・当てはまる
・当てはまらない
・まったく当てはまらない
の4種類の答えをラジオボタンで設定しています。

もちろん、さらに設問数を増やすことも可能ですし、設問数を自在に増減させたい、というご要望もあるでしょうね。
その場合はサブテーブルを使えばよさそうです。
この記事ではサブテーブルではなく、20問に固定したバージョンでお届けしてみます!

実際の内容

  Topへ↑

はい。ではアプリの設定画面です。フォームはこんな感じ。

一番左の文字列フィールドは設問の文字列を入力します。
フィールドコードは上から順にquestion_1からquestion_20としています。

真ん中のドロップダウンフィールドは4つの傾向を選びます。
フィールドコードは上から順にtrend_1からtrend_20としています。

右のラジオボタンフィールドはそれぞれの答えを入力する欄です。
フィールドコードは上から順にanswer_1からanswer_20としています。

で、続いてはグラフを表示するカスタマイズビューを設定してみましょう。

こんな感じですね。

続いてはロジックです。
実は、このグラフを作るには以下の二つのJavaScriptファイルを設定するだけ。

上に設定したのは、Chart.jsです。
Cybozu Developer Network
からCDNのページに移動してもらえれば。

そこのChart.jsに書かれているURLをコピーし、上の画面の
から

に貼って保存するだけ! きとみちゃんでもできますよね?
htttps://がダブらないようにだけ気を付けて!

続いてグラフ表示のロジックです

  Topへ↑

では続いてきとみちゃんとグラフ.jsの内容を。
ここからはVisual Studio Codeの画面にコメントを入れています。




ちょっと見にくいので、直に貼ったコードも提供します。右にスクロールしてくださいね。

(function () {
  "use strict";

  // 一覧ページ
  kintone.events.on('app.record.index.show', function(event) {                       //一覧画面表示時の定型文です
    var record = event.records[0];
    var itemcount = 20;
    var 1_Score = 0;
    var 2_Score = 0;
    var 3_Score = 0;
    var 4_Score = 0;
    var selectedScore = 0;
    var dataLabelPlugin = {                                                          //ここは以下の162行目で呼び出されるチャートのプラグインコンフィグで呼び出される部分です。
      afterDatasetsDraw: function (Chart, easing) {                                  //afterDatasetsDrawとはプラグインコアAPIとして呼び出されるChart.js内部のフックです。要は描画後です。
        var ctx = Chart.ctx;                                                         //チャートが描画されている対象のDOM要素です。157行目で定義され、159行目でChartオブジェクトに渡されます。
        Chart.data.datasets.forEach(function (dataset, i) {                          //対象チャートをループしています。データは77行目で一種類で指定していますのでループは一回のみです。               
          var meta = Chart.getDatasetMeta(i);                                        //チャートのメタデータを取得しています。データやラベルも含まれています。
          if (!meta.hidden) {                                                        //チャートのhiddenプロパティがTrueの場合そもそもチャートが描画されません。
            meta.data.forEach(function (element, index) {                            //メタ要素のデータをループします。今回は4種類ですね。
              ctx.fillStyle = 'rgb(0, 0, 0)';                                        //円グラフの中の文字の色です。rgb(0, 0, 0)は黒を表しています。
              var fontSize = 16;                                                    //36-37行目で文字の場所を設定するためのフォントサイズを16pxで設定しています。表示フォントのサイズとは別に。
              ctx.font = "24px \"Helvetica Neue\", Helvetica, Arial, sans-serif";    //これが実際に描画される文字のフォント情報です

              var sum  = function(arr) {                                             //ここでは対象となるデータの合計値を返します。4種類のデータの合計です。
                  return arr.reduce(function(prev, current, i, arr) {
                      return prev+current;
                  });
              };
              var percentString = ((dataset.data[index] / sum(dataset.data))*100).toFixed(1) + "%";  //それぞれのデータの値を全体の合計で割り、パーセントの文字列を構築します。
              var dataString = Chart.data.labels[index];                                             //それぞれのデータのラベルです。79行目で定義した4つの傾向のラベルですね。 
              ctx.textAlign = 'center';
              ctx.textBaseline = 'middle';

              var padding = 5;
              var position = element.tooltipPosition();
              ctx.fillText(dataString, position.x, position.y - (fontSize / 2) - padding);           //30行目で設定したラベルの値を計算した位置に表示します。
              ctx.fillText(percentString, position.x, position.y - (fontSize / 2) - padding + 35);   //29行目で設定した値のパーセントの文字列を計算した位置に表示します。
            });
          }
        });
      }
    };
    for (var i=1 ; i<=itemcount ; i++){                                                              //ここから76行目までは大人の事情でいろいろとあいまいですがお許しを
      switch( record['answer_' + i]['value'] ) {                                                     //要するに20レコードの設問の答えを基に四つの傾向に加算しているのです
        case 'よく当てはまる':
          selectedScore = 係数は内緒よ♪;
          break;
        case '当てはまる':
          selectedScore = 係数は内緒よ♪;
          break;
        case '当てはまらない':
          selectedScore = 係数は内緒よ♪;
          break;
        case 'まったく当てはまらない':
          selectedScore = 係数は内緒よ♪;
          break;
      }
      switch( record['trend_' + i]['value'] ) {
        case '一つ目の傾向':
          1_Score = 1_Score + selectedScore + 山藤ゆりさんに教えてもらった魔法の値を加えるの♪;           //要するに20レコードの設問の答えを基に四つの傾向に重みづけしているのです
          break;
        case '二つ目の傾向':
          2_Score = 2_Score + selectedScore + 山藤ゆりさんに教えてもらった魔法の値を加えるの♪;
          break;
        case '三つ目の傾向':
          3_Score = 3_Score + selectedScore + 山藤ゆりさんに教えてもらった魔法の値を加えるの♪;
          break;
        case '四つ目の傾向':
          4_Score = 4_Score + selectedScore + 山藤ゆりさんに教えてもらった魔法の値を加えるの♪;
          break;
      }
    }
    1_Score = ロジック関数は内緒よ♪(1_Score);
    2_Score = ロジック関数は内緒よ♪(2_Score);
    3_Score = ロジック関数は内緒よ♪(3_Score);
    4_Score = ロジック関数は内緒よ♪(4_Score);                                          //さらに四つの傾向に値を秘密ロジックで精緻化しています。この辺も大人の事情が絡んでいます。
    var pieChartData = {                                                             //161行目でChartオブジェクトに渡されるデータとラベルと背景色のホバー色や枠の組み合わせです。四要素です。   
      labels : ["リーダー合理系","アイディア活動系","ヘルプ支援系","クール分析系"],       //ラベルですね。四つの要素に分かれています。
      datasets : [                                                                   //四つの要素のそれぞれの色の指定です。
        {
          backgroundColor: [
            '#ff6384',
            '#36a2eb',
            '#cc65fe',
            '#ffce56'
          ],
          hoverBackgroundColor: [
              "#FF2384",
              "#3662EB",
              "#cc25fe",
              "#FF8E56"
          ],
          hoverBorderColor: [
              "#000000",
              "#000000",
              "#000000",
              "#000000"
          ],
          hoverBorderWidth: [
              2,
              2,
              2,
              2
          ],
          data : [1_Score,2_Score,3_Score,4_Score]                                   //四つの要素の値です。大人の事情で実際の回答から複雑に計算された結果が格納されます。
        }
      ]
    }
    var tooltipkeyword = {                                                           //ここは四つの傾向ごとに176行目で乱数を設定し、任意のキーワードを表示するようにしています。
      type : [
        {
          word : [
            '同業者もあの人を噂している',
            '他の部署でも話題になっている',
            '○○さんしかできない',
            '自分で判断し、動ける人',
            '部署のメンバーに信頼されている',
            'あのひとには任せられる'
          ],
          title : "任せる、難題、未知の分野、他に頼めない、誰にもできない"
        },
        {
          word : [
            '発想がおもしろい!!',
            '一緒にいるだけで楽しい!!',
            'さすがアイデアマン!!',
            'すばらしいサービス精神!!',
            'うちの部署のムードメーカー!!',
            'その自由な発想がうらやましい!!'
          ],
          title : "自由にして、思いっきり、楽しく、面白く、みんなでいっしょ"
        },
        {
          word : [
            'みんなが働きに感謝している',
            '縁の下の力持ち',
            '一緒にいて落ち着く',
            '丁寧で親切で信頼できる',
            '細かいところによく気が付く',
            '相手の気持ちを分かってくれる'
          ],
          title : "感謝、ありがとう、仲良く、話し合い、相手の気持ち"
        },
        {
          word : [
            '詳しく業務を理解している',
            '商品のことをよく知っている',
            'わが社のことになんでも詳しい',
            'うちの課の歩く辞書',
            'あの人に聞けば間違いない',
            'このデータ量は大したもの'
          ],
          title : "情報、正確、正しく分析、予定通り、計画通り"
        }
      ]
    }
    var canvas = document.getElementById('canvas').getContext("2d");                 //Chartが描画されるDOM要素を指定するChart.jsの定型文です。id="canvas"はカスタマイズビューで指定しました。
    canvas.canvas.height = 256;                                                      //描画される領域の高さを指定しています。
    var test_chart = new Chart(canvas, {                                             //ここでChartオブジェクトをインスタンスとして実体化させています。
      type: 'pie',                                                                   //type: 'pie'はグラフの種類ですね。円グラフです。
      data: pieChartData,                                                            //77行目で定義したデータの実態です。
      plugins: [dataLabelPlugin],                                                    //プラグインコンフィグで関数を呼び出すことができます。その関数は13行目をご参照ください。
      options: {                                                                     //ここからはオプション情報です。
        animation: {
          animateRotate: true,
          animateScale: true
        },
        tooltips: {
          titleFontSize: 48,
          bodyFontSize: 36,
          callbacks: {
            label: function (tooltipItem, data){                                     //ここは描画後にマウスカーソルが乗った時の事前に内部でtooltipItemに定義された情報を基に値を返します。
                return pieChartData["datasets"][0]['data'][tooltipItem['index']] + "ポイント"       //77行目で定義されたデータから該当するデータを表示し
                  + "  キーワード → " + tooltipkeyword["type"][tooltipItem['index']]["title"];      //さらにキーワードとして109行目で定義された四つの傾向のタイトルを表示します。
            },
            afterLabel: function (tooltipItem, data){                                //172行目のラベルの後に別の情報を表示させるにはafterLabelツールチップコールバックが呼び出せます。
                  return "「" + tooltipkeyword["type"][tooltipItem['index']]["word"][Math.floor(Math.random()*(6-0)+0)] + "」";
            }                                                                        //さらにテキストとして109行目で定義された四つの傾向の文言のオブジェクトから乱数で選ばれた文言を表示します。
          }
        },
      }
    });
  });
})();

あとはこのJavaScriptファイルを

にのようにアップロードしていただければ。

どうでしょう。kintoneのデータにChart.jsを組み合わせるだけで、
kintoneのデータを分析することができてしまうのです。

Chart.jsにはさまざまなグラフが用意されているので、
kintoneの標準グラフでは表現できないことも可能です。

コーチング用の分析ツールとしても使えてしまうkintoneの奥深さを楽しんでいただけたらきとみちゃんも喜ぶはずです!
よかったら以下にChart.jsの公式サイトのリンクも貼っているのでご参考になさってくださいね。

当エントリの参考にさせていただいたブログ

  Topへ↑

最後になりましたが、このエントリ作成にあたり、以下の2サイトおよび、コーチングについて教えて頂いたお客様からの情報を参考にさせていただきました。ありがとうございました。

 Chart.jsドキュメント翻訳
 Chart.js公式サイト


kintone Café 東京 Vol.9を開催しました


11/15にkintone Café 東京 Vol.9を開催しました。

公式の開催報告はしかるべき場所に書かせていただきました。
こちら

関連するツイートのまとめサイトも作成させていただきました。
こちら

なので、ここでは代表である私が登壇の際に語った
kintone Caféとは?スライド
kintoneを簡単にご紹介スライド
Cybozu Days 2019のkintone周りをフィードバックスライド
をさらに補足するように、開催であらためて感じた思いを書かせていただきます。

3月末のkintone Café 広島に登壇した時、今までkintone Caféで話したことのなかった自治会を取り上げました。
今までは技術に即した内容を話すことが多かったのですが、技術に触れないkintone Caféの登壇が私に新鮮でした。

8月末に開催したkintone Café 東京 Vol.8 @多摩では、プロジェクト・アスノートの松田さんと共催しました。
それを機に私の話す内容を思い切って初期化し、kintoneを一から語ってみました。当然技術ネタは封印。

技術ネタだと、kintone Caféに来てくださった方がついて来れない可能性があります。当然、反応も薄くなります。
そもそもkintoneエバンジェリストとは、技術うんぬんではなく、kintoneの良さを広めることにあるのではないか。
私の中でkintone Café神奈川を何度か行う中で迷いが生じていましたが、直近の二回のkintone Caféで修正することができました。

今回のkintone Café 東京 Vol.9は開催要項にユーザー向けをうたっていました。
その一方で、今回の参加者の中には私の知る限り、かなりのスキルを持つ技術者も6,7名はいました。

そうした方々に対し、kintoneの初歩を語ることに意味はあるのか。
私はあると判断しました。
むしろ、技術者であるほど、kintoneが新鮮に映るはず。そうした意味でもユーザー向けの内容でよかったと思います。

今回、会場を提供してくださったのはクロス・ヘッド株式会社様。System Integrateの豊富な経験をお持ちです。
クロス・ヘッド様の会場をお借りしながら、技術に触れず、ユーザー向けの内容にすることに若干のためらいもありました。
ですが、kintone Caféを通しての皆様の反応は上々で、七割以上の方が懇親会に参加してくださいました。その事からも、ユーザー寄りで行く、との方向性は続けようと思いました。

私の登壇では、そもそもなぜkintoneをユーザーに勧めるのか、という観点で一生懸命語ってみたつもりです。
さらに、Cybozu Days 2019 in 東京で発表された内容を報告しました。

今回、一緒に登壇したkintone大好きキンスキ YouTuberの松井さんは、私のPCトラブルによる順番交代にも動じず、見事な登壇を務めてくださいました。そればかりかサイボウズさんならではの事例を提供してくださいました。

私に続いて登壇してくださった情報親方の東野さんは、Cybozu Days 2019で発表され、来場された方々に感心されたkintone導入ガイドブックの制作について、マニュアル制作のノウハウも惜しげなく披露してくださいました。

トリを務めてくださったTeruさんは、登壇を公開できないリスクを押してkintoneが最大に活きる業務改善の生の事例を語ってくださいました。kintoneの紹介から導入、そして業務改善効果に至るまで、今回のCaféを締めるにふさわしい内容でした。

あらためて、こうした地道な活動が、今後につながると確信できた1日でした。
12/7にはkintone Café JAPAN(サイト)が予定されています。そこでもきっと実のある内容が得られる事でしょう。
今回来てくださった35+αの皆様、登壇してくださった3名の仲間。会場を提供してくださったクロス・ヘッド株式会社様。皆さま本当にありがとうございました。


kintone Café 東京 Vol.8 @多摩を開催しました


8/30にkintone Café 東京 Vol.8 @多摩を開催しました。

公式の開催報告はしかるべき場所に書かせていただきました。(こちら

ツイートのまとめサイトも作成させていただきました。(こちら

なので、ここでは代表である私が登壇の際に語った「スライド」をさらに補足するように、開催であらためて感じた思いを書かせていただきます。

本稿を書こうとして、前回アクアビット長井として主催したkintone Caféを調べたところ、2017年3月のkintone Café 神奈川 Vol.5までさかのぼることがわかりました。つまり、前回の開催から2年半、kintone Caféを主催していませんでした。空きすぎです。間を空けすぎたことに忸怩たる思いです。

2年半の間、もちろん手をこまねいていたわけではありません。ツイートもたくさんつぶやきましたし、kintone Advent Calendarにも毎年書いています。DevRelにも参加し、弊社ブログ記事にもkintoneのことは書いています。他のkintone Caféでは登壇もしましたし、お客様の主催するセミナーでも登壇もしました。代表がエバンジェリストとして全く何もしていないとは思いません。kintone Café神奈川もなんどか話を持ち掛けては立ち消えを繰り返し、それなりの開催に向けての準備は進めました。

でも、結局は開催できなかったことに変わりありません。kintone Caféに限らず、セミナーは自らが行うべき。そう思っています。特にkintone開発が弊社の業務の主流になっている今では、一日のほとんどをkintoneの事を考えていたわけですから。これは怠慢と言われても仕方ありません。

何が原因だったか。結局、代表自身がkintone Caféのテーマについて、どう開催するか迷いが生じていたの正直なところです。技術寄りの内容で開催するのか、ユーザー寄りの内容にするのか。技術寄りにしたところで、どこまで伝わるのか。スキルは座学やハンズオンでどこまで伝えられるのか。そもそもkintoneエバンジェリストとは、技術うんぬんではなく、kintoneの良さを広めることにあるのではないか。私の中でコンセプトが右往左往していました。

今回、弊社のサテライトオフィスで開催したのは、オフィスの大家さんから開催要望があったからでした。そして要望の中で「そもそも論」を聞きたい、ということでした。つまりkintoneとはそもそも何か、という地点から話を起こす必要がありました。都合のよいことにkintone Café東京を今運営しているメンバーの松田さんはkintoneを軸とした業務改善を推進されておられます。そうした風もあり、私の登壇資料も技術のことは触れず、ユーザー向けの内容にしてみました。

今回のkintone Café 東京 Vol.8 @多摩は開催要項にユーザー向けをうたっていたこともあり、6,7名はkintoneについて触ったことがなく、そうした意味でもユーザー向けの内容でよかったと思います。私の登壇でもそもそもなぜkintoneをユーザーに勧めるのか、という観点で熱く語りました。他の方のスライドも、そうした点でテーマが絞られていたようです。

今回、久しぶりに主催してみて、ユーザー寄りで行く、との方向性は続けようと思いました。ただ、ハンズオンはやれればやりたい。一緒に登壇したエバンジェリストの新妻さんからも、「データ」「プロセス」「コミュニケーション」の三つの柱で語るのは、初期のkintoneのコンセプト。今や概念で語るのではなく、直接ハンズオンで魅力を伝えることの必要性を説かれました。仰る通りで、次回はハンズオンにも取り掛からねば、と思います。

今回、一緒に登壇した情報親方の東野さんも、これからkintoneが導入されていく中で必ず使われるであろう資料を軽く紹介してくださいました。やはりユーザー導入の推進こそが鍵なのでしょう。

お客様より恵比寿と武蔵小杉でもkintone Caféを開催して欲しいというご要望をいただいています。具体的に会場も確保できています。今年はあと二回、開催できればと思います。その時私が、どこまで技術を語りたいという誘惑に耐え、ユーザー目線の内容に踏みとどまれるか。肝に銘じたいと思います。まずはkintone Caféを主催できる自信を取り戻せたことが、今回、私の中で最も得難い収穫だったと思います。

今回来てくださった14名の皆様、登壇してくださった3名の仲間。皆様、本当にありがとうございました。