From 733c9a9eb84d14a26fd5368022a9ad433ee705a7 Mon Sep 17 00:00:00 2001 From: "sosuke.iwabuchi" Date: Thu, 14 Dec 2023 12:23:36 +0900 Subject: [PATCH] =?UTF-8?q?=E5=88=9D=E5=9B=9E=E5=85=A5=E9=87=91=E5=AF=BE?= =?UTF-8?q?=E5=BF=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/apps/入金予定結果/index.tsx | 109 +++++++++++++++--- src/apps/定期申込予約/index.tsx | 47 ++++---- src/apps/定期申込予約/自動承認.ts | 26 +++-- src/common/app-template.ts | 45 ++++++++ src/common/appids.ts | 1 + src/common/kintone-event.ts | 39 +++++++ src/rest-api/bulk.ts | 1 + src/rest-api/定期申込予約.ts | 16 +++ .../定期駐車場プランマスタ.ts | 35 ++++++ src/types/定期申込予約.ts | 18 ++- 10 files changed, 282 insertions(+), 55 deletions(-) create mode 100644 src/common/app-template.ts create mode 100644 src/common/kintone-event.ts create mode 100644 src/rest-api/定期申込予約.ts create mode 100644 src/rest-api/定期駐車場プランマスタ.ts diff --git a/src/apps/入金予定結果/index.tsx b/src/apps/入金予定結果/index.tsx index 456e2ae..0def89b 100644 --- a/src/apps/入金予定結果/index.tsx +++ b/src/apps/入金予定結果/index.tsx @@ -1,9 +1,15 @@ +import { eventHnalder } from "@/common/app-template"; import { AppID } from "@/common/appids"; import { setHeaderButton } from "@/common/header-button"; +import { KintoneEvent, 値設定 } from "@/common/kintone-event"; import { makeRecordData } from "@/common/rest-api-client"; +import { Message } from "@/exception"; import { EmailID, sendEmail } from "@/mypage/メール"; import { makeReceipt } from "@/mypage/領収証発行"; +import { BulkRequest } from "@/rest-api/bulk"; +import { get定期申込予約 } from "@/rest-api/定期申込予約"; import { 入金予定結果, 入金予定結果フィールド名 } from "@/types/入金予定結果"; +import { 定期申込予約フィールド名 } from "@/types/定期申込予約"; import { KintoneRestAPIClient } from "@kintone/rest-api-client"; import { format } from "date-fns"; import Swal from "sweetalert2"; @@ -74,8 +80,7 @@ const setData = (event: any, targets: string[]) => { targets.forEach((target) => { const value = param.get(target); if (value === null) return; - event.record[target].value = value; - event.record[target].lookup = true; + 値設定(event, target, value, true); }); }; (() => { @@ -92,7 +97,61 @@ const setData = (event: any, targets: string[]) => { } }); - kintone.events.on("app.record.create.show", (event) => { + const 初回請求金額確定チェック = (record: 入金予定結果) => { + if (!record.first_payment_entry_record_no.value) { + throw new Message("初回振り込み関連申込レコード番号が入力されていません"); + } + + // 申込の初回振り込み情報を入力する + const F = 定期申込予約フィールド名; + const 支払予定日 = record.payment_plan_date.value; + if (!支払予定日) { + throw new Message("支払予定日が入力されていません"); + } + const 支払予定金額 = record.payment_plan_amount.value; + if (!支払予定金額) { + throw new Message("支払予定金額が入力されていません"); + } + }; + const 初回請求金額確定 = async (record: 入金予定結果) => { + 初回請求金額確定チェック(record); + + const 申込 = await get定期申込予約( + record.first_payment_entry_record_no.value + ); + + // 申込の初回振り込み情報を入力する + const F = 定期申込予約フィールド名; + const 支払予定日 = record.payment_plan_date.value ?? ""; + const 支払予定金額 = record.payment_plan_amount.value ?? ""; + + const 日割り金額 = Number(支払予定金額) - Number(申込.定期駐車料金.value); + const 日割り月 = (() => { + if (日割り金額 === 0) return ""; + let month = Number(record.target_month.value) - 1; + if (month === 0) { + month = 12; + } + return String(month); + })(); + + const request = new BulkRequest(); + request.update({ + app: AppID.定期申込予約, + id: record.first_payment_entry_record_no.value, + record: makeRecordData({ + [F.振込期日]: 支払予定日, + [F.初回振り込み合計額]: 支払予定金額, + [F.請求対象分_月]: record.target_month.value, + [F.請求対象分_金額]: 申込.定期駐車料金.value, + [F.日割り分_金額]: String(日割り金額), + [F.日割り分_月]: 日割り月, + }), + }); + await request.save(); + }; + + kintone.events.on(KintoneEvent.追加.レコード追加画面を表示した後, (event) => { setData(event, [ 入金予定結果フィールド名.車室契約情報レコード番号, 入金予定結果フィールド名.初回振り込み関連申込レコード番号, @@ -100,18 +159,34 @@ const setData = (event: any, targets: string[]) => { return event; }); - kintone.events.on("app.record.create.submit.success", (event) => { - const record = event.record as 入金予定結果; - // 初回請求確定時にはメールを送信する - if ( - record[入金予定結果フィールド名.初回振り込み関連申込レコード番号].value - ) { - sendEmail(EmailID.申込受付, { - season_ticket_contract_entry_record_no: Number( - record[入金予定結果フィールド名.初回振り込み関連申込レコード番号] - .value - ), - }); - } - }); + kintone.events.on( + KintoneEvent.追加.保存するとき, + eventHnalder(async (event: any) => { + const record = event.record as 入金予定結果; + // 初回請求確定時にはメールを送信する + if ( + record[入金予定結果フィールド名.初回振り込み関連申込レコード番号].value + ) { + await 初回請求金額確定(record); + } + }) + ); + kintone.events.on( + KintoneEvent.追加.保存に成功した後, + eventHnalder(async (event: any) => { + const record = event.record as 入金予定結果; + // 初回請求確定時にはメールを送信する + if ( + record[入金予定結果フィールド名.初回振り込み関連申込レコード番号].value + ) { + // メール送信 + sendEmail(EmailID.申込受付, { + season_ticket_contract_entry_record_no: Number( + record[入金予定結果フィールド名.初回振り込み関連申込レコード番号] + .value + ), + }); + } + }) + ); })(); diff --git a/src/apps/定期申込予約/index.tsx b/src/apps/定期申込予約/index.tsx index a84028b..6eece29 100644 --- a/src/apps/定期申込予約/index.tsx +++ b/src/apps/定期申込予約/index.tsx @@ -7,10 +7,11 @@ import { SuccessDialog, WarningDialog, } from "@/middleware/swal"; -import { getCreateUrl } from "@/rest-api/url"; +import { getCreateUrl, getDetailUrl } from "@/rest-api/url"; import { 入金予定結果フィールド名 } from "@/types/入金予定結果"; import { 定期申込予約 } from "@/types/定期申込予約"; import { 申込 } from "./自動承認"; +import { apptemplate } from "@/common/app-template"; (() => { console.info("script build at " + process.env.BUILD_TIME); @@ -19,13 +20,14 @@ import { 申込 } from "./自動承認"; const record: 定期申込予約 = event.record; if (!record.auto_confirm_status.value) { - setHeaderButton("自動承認", async () => { - const confirm = await ShowConfirmDialog({ - text: "承認しますか", - }); - if (!confirm.isConfirmed) return; + setHeaderButton( + "自動承認", + apptemplate(async () => { + const confirm = await ShowConfirmDialog({ + text: "承認しますか", + }); + if (!confirm.isConfirmed) return; - try { const entry = new 申込(record); await entry.初期化(); await entry.選定(); @@ -45,25 +47,22 @@ import { 申込 } from "./自動承認"; [入金予定結果フィールド名.初回振り込み関連申込レコード番号]: record.$id.value, }); - const url = getCreateUrl(AppID.入金予定結果, param); - console.log(url, param); - window.open(url, "_blank"); + { + // 入金予定アプリ画面オープン + 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(); - } catch (e) { - if (e instanceof CancelError) { - console.log("canceled"); - return; - } else if (e instanceof Message) { - ErrorDialog.fire({ - text: e.message, - }); - return; - } - ErrorDialog.fire(); - throw e; - } - }); + }) + ); } }); })(); diff --git a/src/apps/定期申込予約/自動承認.ts b/src/apps/定期申込予約/自動承認.ts index 984a058..f31647b 100644 --- a/src/apps/定期申込予約/自動承認.ts +++ b/src/apps/定期申込予約/自動承認.ts @@ -1,14 +1,10 @@ import { AppID } from "@/common/appids"; import { makeRecordData } from "@/common/rest-api-client"; import { 契約状況同期 } from "@/logic/契約状況同期"; -import { - ConfirmDialog, - ShowConfirmDialog, - showLoadingDialog, -} from "@/middleware/swal"; -import { EmailID, sendEmail } from "@/mypage/メール"; +import { ShowConfirmDialog } from "@/middleware/swal"; import { BulkRequest } from "@/rest-api/bulk"; import { getDetailUrl } from "@/rest-api/url"; +import { get定期駐車場プランマスタ } from "@/rest-api/定期駐車場プランマスタ"; import { get自動承認グループ } from "@/rest-api/自動承認グループ"; import { get車室契約情報, get車室契約情報一覧 } from "@/rest-api/車室契約情報"; import { get車室情報一覧 } from "@/rest-api/車室情報2"; @@ -23,14 +19,13 @@ import { 状態Dropdown, 自動承認ステータスDropdown, } from "@/types/定期申込予約"; +import { 定期駐車場プランマスタ } from "@/types/定期駐車場プランマスタ"; import { 自動承認グループ } from "@/types/自動承認グループ"; import { 車室契約情報, 車室契約情報フィールド名 } from "@/types/車室契約情報"; import { 車室情報2 } from "@/types/車室情報2"; import { 顧客マスタフィールド名 } from "@/types/顧客マスタ"; import { sprintf } from "sprintf"; -import { CancelError, Message } from "../../exception"; -import { 入金予定結果フィールド名 } from "@/types/入金予定結果"; -import { dateParse, now } from "@/common/datetime"; +import { CancelError, Message } from "@/exception"; export class 申込 { private 定期申込予約: 定期申込予約; @@ -43,6 +38,7 @@ export class 申込 { private 車室一覧: 車室情報2[] = []; private 契約一覧: 車室契約情報[] = []; private 自動承認グループ: 自動承認グループ | null = null; + private プラン: 定期駐車場プランマスタ | null = null; private 作成後契約: 車室契約情報 | null = null; @@ -59,6 +55,8 @@ export class 申込 { await this.契約情報取得(); // 自動承認データの取得 await this.自動承認グループ取得(); + // 定期駐車場プランマスタデータの取得 + await this.プラン取得(); this.初期化済み = true; return this; @@ -117,6 +115,14 @@ export class 申込 { this.定期申込予約.定期駐車場プラン.value ); } + private async プラン取得() { + if (!this.定期申込予約.定期駐車場プラン.value) { + throw new Message("プラン名の設定をしてください"); + } + this.プラン = await get定期駐車場プランマスタ( + this.定期申込予約.定期駐車場プラン.value + ); + } private 対象車室取得() { if (!this.初期化済み) { @@ -227,6 +233,7 @@ export class 申込 { } private async 申込情報完了() { + if (this.プラン === null) throw new Error(); const F = 定期申込予約フィールド名; this.requests.update({ app: AppID.定期申込予約, @@ -234,6 +241,7 @@ export class 申込 { record: makeRecordData({ [F.状態]: 状態Dropdown.承認_自動承認, [F.自動承認ステータス]: 自動承認ステータスDropdown.承認済, + [F.定期駐車料金]: this.プラン.契約金額.value, }), }); } diff --git a/src/common/app-template.ts b/src/common/app-template.ts new file mode 100644 index 0000000..9e27644 --- /dev/null +++ b/src/common/app-template.ts @@ -0,0 +1,45 @@ +import { CancelError, Message } from "@/exception"; +import { ErrorDialog } from "@/middleware/swal"; + +export const apptemplate = (callback: () => Promise) => { + return async () => { + try { + const ret = await callback(); + } catch (e) { + if (e instanceof CancelError) { + console.log("canceled"); + return; + } else if (e instanceof Message) { + ErrorDialog.fire({ + text: e.message, + }); + return; + } + ErrorDialog.fire(); + throw e; + } + }; +}; + +export const eventHnalder = (callback: (event: any) => Promise) => { + return async (event: any) => { + try { + const ret = await callback(event); + return ret; + } catch (e) { + if (e instanceof CancelError) { + console.log("canceled"); + return false; + } else if (e instanceof Message) { + console.error("message", e.message); + ErrorDialog.fire({ + text: e.message, + }); + return false; + } + ErrorDialog.fire(); + console.error(e); + return false; + } + }; +}; diff --git a/src/common/appids.ts b/src/common/appids.ts index 4862d68..bd153a9 100644 --- a/src/common/appids.ts +++ b/src/common/appids.ts @@ -12,5 +12,6 @@ export const AppID = { 車室契約情報: APP_ID.車室契約情報, 車室情報2: APP_ID.車室情報2, 自動承認グループ: APP_ID.自動承認グループ, + 定期駐車場プランマスタ: APP_ID.定期駐車場プランマスタ, } as const; export type AppID = (typeof AppID)[keyof typeof AppID]; diff --git a/src/common/kintone-event.ts b/src/common/kintone-event.ts new file mode 100644 index 0000000..8c779fb --- /dev/null +++ b/src/common/kintone-event.ts @@ -0,0 +1,39 @@ +export const KintoneEvent = { + 一覧: { + 一覧画面を表示した後: "app.record.index.show", + }, + + 詳細: { + レコード詳細画面を表示した後: "app.record.detail.show", + レコードを削除する前: "app.record.detail.delete.submit", + プロセス管理のアクションを実行したとき: "app.record.detail.process.proceed", + }, + // レコード追加画面 + 追加: { + レコード追加画面を表示した後: "app.record.create.show", + 保存するとき: "app.record.create.submit", + 保存に成功した後: "app.record.create.submit.success", + }, + + // レコード編集画面 + 編集: { + レコード編集画面を表示した後: "app.record.edit.show", + 保存するとき: "app.record.edit.show", + 保存に成功した後: "app.record.edit.success", + }, +} as const; + +export const 画面遷移 = (event: any, url: string) => { + event.url = url; +}; +export const 値設定 = ( + event: any, + target: string, + value: any, + lookup: boolean = false +) => { + event.record[target].value = value; + if (lookup) { + event.record[target].lookup = true; + } +}; diff --git a/src/rest-api/bulk.ts b/src/rest-api/bulk.ts index 53e0e5c..e66d74b 100644 --- a/src/rest-api/bulk.ts +++ b/src/rest-api/bulk.ts @@ -74,6 +74,7 @@ export class BulkRequest { } async save() { + this.debug(); let results: BulkRequestResponse[] = []; for (const requests of chunk(this.requests, 20)) { const res = await this.client.bulkRequest({ requests }); diff --git a/src/rest-api/定期申込予約.ts b/src/rest-api/定期申込予約.ts new file mode 100644 index 0000000..89f2477 --- /dev/null +++ b/src/rest-api/定期申込予約.ts @@ -0,0 +1,16 @@ +import { AppID } from "@/common/appids"; +import { 定期申込予約 } from "@/types/定期申込予約"; +import { KintoneRestAPIClient } from "@kintone/rest-api-client"; + +const client = new KintoneRestAPIClient(); + +export const get定期申込予約 = async ( + レコード番号: string | number +): Promise<定期申込予約> => { + const { record } = await client.record.getRecord<定期申込予約>({ + app: AppID.定期申込予約, + id: レコード番号, + }); + + return record; +}; diff --git a/src/rest-api/定期駐車場プランマスタ.ts b/src/rest-api/定期駐車場プランマスタ.ts new file mode 100644 index 0000000..bfd5149 --- /dev/null +++ b/src/rest-api/定期駐車場プランマスタ.ts @@ -0,0 +1,35 @@ +import { AppID } from "@/common/appids"; +import { + 定期駐車場プランマスタ, + 定期駐車場プランマスタフィールド名, +} from "@/types/定期駐車場プランマスタ"; +import { KintoneRestAPIClient } from "@kintone/rest-api-client"; +import { sprintf } from "sprintf"; + +const client = new KintoneRestAPIClient(); + +export const get定期駐車場プランマスタ = async ( + プラン名: string +): Promise<定期駐車場プランマスタ> => { + const query = sprintf( + sprintf('%s = "%s"', 定期駐車場プランマスタフィールド名.プラン名, プラン名) + ); + + const { records } = await client.record.getRecords<定期駐車場プランマスタ>({ + app: AppID.定期駐車場プランマスタ, + query, + }); + + if (records.length !== 1) { + throw new Error( + sprintf( + "定期駐車場プランマスタ取得数数エラー expect %d, actual %d query:%s", + 1, + records.length, + query + ) + ); + } + + return records[0]; +}; diff --git a/src/types/定期申込予約.ts b/src/types/定期申込予約.ts index 69228c7..eb94c5a 100644 --- a/src/types/定期申込予約.ts +++ b/src/types/定期申込予約.ts @@ -5,6 +5,14 @@ const F = { 状態: "status", 自動承認ステータス: "auto_confirm_status", 利用開始希望日: "利用開始希望日", + + 定期駐車料金: "定期駐車料金", + 振込期日: "振込期日", + 日割り分_月: "日割り分_月", + 日割り分_金額: "日割り分_金額", + 請求対象分_月: "請求対象分_月", + 請求対象分_金額: "請求対象分_金額", + 初回振り込み合計額: "初回振り込み合計額", } as const; export const 状態Dropdown = { @@ -38,12 +46,12 @@ export type 定期申込予約 = AppRecord & { 台数: KintoneRecordField.SingleLineText; 防犯登録番号: KintoneRecordField.SingleLineText; 請求対象分_月: KintoneRecordField.Number; - 初回振り込み合計額: KintoneRecordField.Number; + [F.初回振り込み合計額]: KintoneRecordField.Number; メールアドレス: KintoneRecordField.SingleLineText; 受付日時: KintoneRecordField.DateTime; 学生手帳: KintoneRecordField.SingleLineText; 氏名: KintoneRecordField.SingleLineText; - 定期駐車料金: KintoneRecordField.Number; + [F.定期駐車料金]: KintoneRecordField.Number; 学校名: KintoneRecordField.SingleLineText; 住所: KintoneRecordField.SingleLineText; 電話番号: KintoneRecordField.SingleLineText; @@ -55,13 +63,13 @@ export type 定期申込予約 = AppRecord & { 車室番号: KintoneRecordField.SingleLineText; ParkingNavi駐車場: KintoneRecordField.SingleLineText; 駐車場: KintoneRecordField.SingleLineText; - 振込期日: KintoneRecordField.Date; + [F.振込期日]: KintoneRecordField.Date; 日割り分_金額: KintoneRecordField.Number; 自動承認メモ: KintoneRecordField.MultiLineText; 車両番号: KintoneRecordField.SingleLineText; - 請求対象分_金額: KintoneRecordField.Number; + [F.請求対象分_金額]: KintoneRecordField.Number; ParkingNaviプラン: KintoneRecordField.SingleLineText; - 日割り分_月: KintoneRecordField.Number; + [F.日割り分_月]: KintoneRecordField.Number; 支払方法: KintoneRecordField.Dropdown; [F.自動承認ステータス]: KintoneRecordField.SingleLineText; [F.状態]: KintoneRecordField.Dropdown;