From e29f21b0c97a87fdb380535e4bb4ccd6de6d02da Mon Sep 17 00:00:00 2001 From: "sosuke.iwabuchi" Date: Mon, 18 Dec 2023 16:43:24 +0900 Subject: [PATCH] =?UTF-8?q?=E3=82=A4=E3=83=99=E3=83=B3=E3=83=88=E5=87=A6?= =?UTF-8?q?=E7=90=86=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/apps/index.ts | 8 ++ src/apps/定期申込予約/index.tsx | 98 ++++++++++--------- src/apps/定期申込予約/自動承認.ts | 6 -- .../customize-manifest.json | 12 +++ src/apps/車室契約情報/index.ts | 16 +++ src/common/app-template.ts | 82 +++++++++++++++- src/common/kintone-event.ts | 4 +- src/config/event.ts | 10 ++ src/event/base.ts | 30 ++++++ src/event/manager.ts | 56 +++++++++++ src/event/契約情報更新.ts | 14 +++ 11 files changed, 278 insertions(+), 58 deletions(-) create mode 100644 src/apps/index.ts create mode 100644 src/apps/車室契約情報/customize-manifest.json create mode 100644 src/apps/車室契約情報/index.ts create mode 100644 src/config/event.ts create mode 100644 src/event/base.ts create mode 100644 src/event/manager.ts create mode 100644 src/event/契約情報更新.ts diff --git a/src/apps/index.ts b/src/apps/index.ts new file mode 100644 index 0000000..e719168 --- /dev/null +++ b/src/apps/index.ts @@ -0,0 +1,8 @@ +import { eventInit } from "@/config/event"; + +export const setup = (callback: VoidFunction) => { + console.info("script build at " + process.env.BUILD_TIME); + + eventInit(); + callback(); +}; diff --git a/src/apps/定期申込予約/index.tsx b/src/apps/定期申込予約/index.tsx index 6eece29..ebb0b68 100644 --- a/src/apps/定期申込予約/index.tsx +++ b/src/apps/定期申込予約/index.tsx @@ -12,57 +12,63 @@ import { 入金予定結果フィールド名 } from "@/types/入金予定結果 import { 定期申込予約 } from "@/types/定期申込予約"; import { 申込 } from "./自動承認"; import { apptemplate } from "@/common/app-template"; +import { setup } from ".."; +import { KintoneEvent } from "@/common/kintone-event"; +import { 契約情報更新イベント } from "@/event/契約情報更新"; -(() => { - console.info("script build at " + process.env.BUILD_TIME); +setup(() => { + kintone.events.on( + [KintoneEvent.詳細.レコード詳細画面を表示した後], + (event) => { + const record: 定期申込予約 = event.record; - kintone.events.on("app.record.detail.show", (event) => { - const record: 定期申込予約 = event.record; + if (!record.auto_confirm_status.value) { + setHeaderButton( + "自動承認", + apptemplate(async ({ setEvent, needReloadAtEnd }) => { + const confirm = await ShowConfirmDialog({ + text: "承認しますか", + }); + if (!confirm.isConfirmed) return; - if (!record.auto_confirm_status.value) { - setHeaderButton( - "自動承認", - apptemplate(async () => { - const confirm = await ShowConfirmDialog({ - text: "承認しますか", - }); - if (!confirm.isConfirmed) return; + const entry = new 申込(record); + await entry.初期化(); + await entry.選定(); - const entry = new 申込(record); - await entry.初期化(); - await entry.選定(); + await SuccessDialog.fire(); - await SuccessDialog.fire(); + await WarningDialog.fire({ + timer: 2000, + timerProgressBar: true, + text: "初回請求データを作成してください", + }); + const 契約 = entry.作成後契約取得(); + if (!契約) throw new Error(); - await WarningDialog.fire({ - timer: 2000, - timerProgressBar: true, - text: "初回請求データを作成してください", - }); - const 契約 = entry.作成後契約取得(); - if (!契約) throw new Error(); + const param = new URLSearchParams({ + [入金予定結果フィールド名.車室契約情報レコード番号]: + 契約.$id.value, + [入金予定結果フィールド名.初回振り込み関連申込レコード番号]: + record.$id.value, + }); + { + // 入金予定アプリ画面オープン + const url = getCreateUrl(AppID.入金予定結果, param); + console.log(url, param); + window.open(url, "_blank"); + } + { + // 車室契約情報アプリ画面オープン + const url = getDetailUrl(AppID.車室契約情報, 契約.$id.value); + console.log(url, param); + window.open(url, "_blank"); + } - const param = new URLSearchParams({ - [入金予定結果フィールド名.車室契約情報レコード番号]: 契約.$id.value, - [入金予定結果フィールド名.初回振り込み関連申込レコード番号]: - record.$id.value, - }); - { - // 入金予定アプリ画面オープン - const url = getCreateUrl(AppID.入金予定結果, param); - console.log(url, param); - window.open(url, "_blank"); - } - { - // 車室契約情報アプリ画面オープン - const url = getDetailUrl(AppID.車室契約情報, 契約.$id.value); - console.log(url, param); - window.open(url, "_blank"); - } - - location.reload(); - }) - ); + setEvent(new 契約情報更新イベント().getEvent(契約)); + needReloadAtEnd(true); + }) + ); + } } - }); -})(); + ); +}); diff --git a/src/apps/定期申込予約/自動承認.ts b/src/apps/定期申込予約/自動承認.ts index fe89a7a..84f6176 100644 --- a/src/apps/定期申込予約/自動承認.ts +++ b/src/apps/定期申込予約/自動承認.ts @@ -1,6 +1,5 @@ import { AppID } from "@/common/appids"; import { makeRecordData } from "@/common/rest-api-client"; -import { 契約状況同期 } from "@/logic/契約状況同期"; import { ShowConfirmDialog } from "@/middleware/swal"; import { getDetailUrl } from "@/rest-api/url"; import { get定期駐車場プランマスタ } from "@/rest-api/定期駐車場プランマスタ"; @@ -73,11 +72,6 @@ export class 申込 { // データ保存 await this.save(); - - await 契約状況同期( - this.定期申込予約.駐車場.value, - Number(target.車室番号.value) - ); } 選定情報取得() { diff --git a/src/apps/車室契約情報/customize-manifest.json b/src/apps/車室契約情報/customize-manifest.json new file mode 100644 index 0000000..a84f791 --- /dev/null +++ b/src/apps/車室契約情報/customize-manifest.json @@ -0,0 +1,12 @@ +{ + "app": "", + "scope": "ALL", + "desktop": { + "js": ["dist/車室契約情報.js"], + "css":[] + }, + "mobile": { + "js": [], + "css":[] + } +} diff --git a/src/apps/車室契約情報/index.ts b/src/apps/車室契約情報/index.ts new file mode 100644 index 0000000..1c8b355 --- /dev/null +++ b/src/apps/車室契約情報/index.ts @@ -0,0 +1,16 @@ +import { eventHnalder } from "@/common/app-template"; +import { KintoneEvent } from "@/common/kintone-event"; +import { 契約情報更新イベント } from "@/event/契約情報更新"; +import { 車室契約情報 } from "@/types/車室契約情報"; +import { setup } from ".."; + +setup(() => { + kintone.events.on( + [KintoneEvent.追加.保存に成功した後, KintoneEvent.編集.保存に成功した後], + eventHnalder(async (event, { setEvent }) => { + const record = event.record as 車室契約情報; + + setEvent(new 契約情報更新イベント().getEvent(record)); + }) + ); +}); diff --git a/src/common/app-template.ts b/src/common/app-template.ts index 82a56d1..47c079f 100644 --- a/src/common/app-template.ts +++ b/src/common/app-template.ts @@ -1,10 +1,53 @@ +import eventManager from "@/event/manager"; import { CancelError, Message } from "@/exception"; import { ErrorDialog } from "@/middleware/swal"; +import bulkRequest from "@/rest-api/bulk"; -export const apptemplate = (callback: () => Promise) => { +export const apptemplate = ( + callback: (options: { + setEvent: (event: Event) => void; + needReloadAtEnd: (need: boolean) => void; + }) => Promise +) => { return async () => { try { - await callback(); + const events: Event[] = []; + let needReloadAtEnd = false; + + await callback({ + setEvent: (event: Event) => { + events.push(event); + }, + needReloadAtEnd: (need: boolean) => { + needReloadAtEnd = need; + }, + }); + + // 保存処理 + if (!bulkRequest.isSaved()) { + await bulkRequest.save(); + } + + // イベント処理 + if (events.length !== 0) { + console.log("イベント発生"); + eventManager.init(); + for (const [index, event] of events.entries()) { + window.dispatchEvent(event); + } + await eventManager.waitEnd(); + console.log("イベント処理終了"); + } + + // 保存処理 + if (!bulkRequest.isSaved()) { + await bulkRequest.save(); + } + + // 再読込 + if (needReloadAtEnd) { + location.reload(); + } } catch (e) { if (e instanceof CancelError) { console.log("canceled"); @@ -21,10 +64,41 @@ export const apptemplate = (callback: () => Promise) => { }; }; -export const eventHnalder = (callback: (event: any) => Promise) => { +export const eventHnalder = ( + callback: ( + event: any, + options: { setEvent: (event: Event) => void } + ) => Promise +) => { return async (event: any) => { try { - const ret = await callback(event); + const events: Event[] = []; + const ret = await callback(event, { + setEvent: (event: Event) => { + events.push(event); + }, + }); + + // 保存処理 + if (!bulkRequest.isSaved()) { + await bulkRequest.save(); + } + + // イベント処理 + if (events.length !== 0) { + console.log("イベント発生"); + eventManager.init(); + for (const [index, event] of events.entries()) { + window.dispatchEvent(event); + } + await eventManager.waitEnd(); + console.log("イベント処理終了"); + } + + // 保存処理 + if (!bulkRequest.isSaved()) { + await bulkRequest.save(); + } return ret; } catch (e) { if (e instanceof CancelError) { diff --git a/src/common/kintone-event.ts b/src/common/kintone-event.ts index 8c779fb..ba3c1a0 100644 --- a/src/common/kintone-event.ts +++ b/src/common/kintone-event.ts @@ -18,8 +18,8 @@ export const KintoneEvent = { // レコード編集画面 編集: { レコード編集画面を表示した後: "app.record.edit.show", - 保存するとき: "app.record.edit.show", - 保存に成功した後: "app.record.edit.success", + 保存するとき: "app.record.edit.submit", + 保存に成功した後: "app.record.edit.submit.success", }, } as const; diff --git a/src/config/event.ts b/src/config/event.ts new file mode 100644 index 0000000..17b35d0 --- /dev/null +++ b/src/config/event.ts @@ -0,0 +1,10 @@ +import { ModelChangeEvent } from "@/event/base"; +import { 契約情報更新イベント } from "@/event/契約情報更新"; + +const events: ModelChangeEvent[] = [new 契約情報更新イベント()]; + +export const eventInit = () => { + events.forEach((event) => { + event.register(); + }); +}; diff --git a/src/event/base.ts b/src/event/base.ts new file mode 100644 index 0000000..12e4409 --- /dev/null +++ b/src/event/base.ts @@ -0,0 +1,30 @@ +import eventManager from "./manager"; + +interface ModelChangeEventParam { + record: T; +} + +export abstract class ModelChangeEvent { + abstract eventname(): string; + + abstract listener(record: T): Promise; + + register() { + const callback = async (event: Event): Promise => { + const customEvent = event as CustomEvent>; + eventManager.start(); + await this.listener(customEvent.detail.record); + eventManager.end(); + }; + + console.log("イベント登録", this.eventname()); + window.addEventListener(this.eventname(), callback); + } + + getEvent(record: T) { + const event = new CustomEvent>(this.eventname(), { + detail: { record }, + }); + return event; + } +} diff --git a/src/event/manager.ts b/src/event/manager.ts new file mode 100644 index 0000000..7ea85aa --- /dev/null +++ b/src/event/manager.ts @@ -0,0 +1,56 @@ +class EventManager { + private promise: Promise | null = null; + private resolve: VoidFunction | null = null; + + private execCount: number = 0; + + private timer: NodeJS.Timeout | null = null; + + init() { + this.clear(); + + this.promise = new Promise((resolve) => { + this.resolve = resolve; + }); + + // 一定時間内にイベントの開始を検知しない場合は終了する + this.timer = setTimeout(() => { + if (this.resolve !== null) { + this.resolve(); + } + console.log("イベント発生なし"); + }, 1000); + } + + start() { + this.execCount++; + if (this.timer !== null) { + clearTimeout(this.timer); + } + } + + end() { + this.execCount--; + if (this.execCount === 0) { + if (this.resolve !== null) { + console.log("イベント監視終了"); + this.resolve(); + } + } + } + + waitEnd() { + if (this.promise === null) throw new Error("EventManager init不正"); + return this.promise; + } + + clear() { + this.promise = null; + this.resolve = null; + this.execCount = 0; + this.timer = null; + } +} + +const eventManager = new EventManager(); +export default eventManager; diff --git a/src/event/契約情報更新.ts b/src/event/契約情報更新.ts new file mode 100644 index 0000000..ada6b3c --- /dev/null +++ b/src/event/契約情報更新.ts @@ -0,0 +1,14 @@ +import { 車室契約情報 } from "@/types/車室契約情報"; +import { ModelChangeEvent } from "./base"; +import { 契約状況同期 } from "@/logic/契約状況同期"; + +export class 契約情報更新イベント extends ModelChangeEvent<車室契約情報> { + eventname(): string { + return "契約情報更新イベント"; + } + + async listener(record: 車室契約情報): Promise { + console.log("同期"); + await 契約状況同期(record.駐車場名.value, Number(record.車室番号.value)); + } +}