From 8705a2ffb3c0860457558bab5d7dbe10ff9ff6a2 Mon Sep 17 00:00:00 2001 From: "sosuke.iwabuchi" Date: Thu, 1 Feb 2024 23:39:38 +0900 Subject: [PATCH] =?UTF-8?q?=E5=88=9D=E5=9B=9E=E8=AB=8B=E6=B1=82=E5=88=86?= =?UTF-8?q?=E5=AF=BE=E5=BF=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/apps/入金予定結果/index.tsx | 167 ++++++------------ .../保証金入金予定作成ボタン.ts | 90 ++++++++++ .../初月分入金予定作成ボタン.ts | 71 ++++++++ .../buttons/受付メール送信ボタン.ts | 84 +++++++++ .../日割り入金予定作成ボタン.ts | 67 +++++++ .../buttons/自動承認ボタン.ts | 59 +++++++ src/apps/定期申込予約/index.tsx | 137 ++------------ src/apps/定期申込予約/自動承認.ts | 16 ++ src/common/datetime.ts | 6 +- src/common/rest-api-client.ts | 26 +++ src/rest-api/url.ts | 22 +++ src/types/入金予定結果.ts | 39 ++++ src/types/定期申込予約.ts | 21 +++ 13 files changed, 567 insertions(+), 238 deletions(-) create mode 100644 src/apps/定期申込予約/buttons/保証金入金予定作成ボタン.ts create mode 100644 src/apps/定期申込予約/buttons/初月分入金予定作成ボタン.ts create mode 100644 src/apps/定期申込予約/buttons/受付メール送信ボタン.ts create mode 100644 src/apps/定期申込予約/buttons/日割り入金予定作成ボタン.ts create mode 100644 src/apps/定期申込予約/buttons/自動承認ボタン.ts diff --git a/src/apps/入金予定結果/index.tsx b/src/apps/入金予定結果/index.tsx index 7dcf371..21a54c0 100644 --- a/src/apps/入金予定結果/index.tsx +++ b/src/apps/入金予定結果/index.tsx @@ -4,28 +4,67 @@ import { formatDateStr, today } from "@/common/datetime"; import { initMenuBox, 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 { get定期駐車場プランマスタ } from "@/rest-api/定期駐車場プランマスタ"; -import { get車室情報管理 } from "@/rest-api/車室情報管理"; +import { parseFromUrlSearchQuery } from "@/rest-api/url"; import { get顧客マスタ } from "@/rest-api/顧客マスタ"; import { 入金予定結果, 入金予定結果フィールド名, + 定期料金日割り分Checkbox, 支払種別Dropdown, } from "@/types/入金予定結果"; import { 定期申込予約フィールド名 } from "@/types/定期申込予約"; -import { 車室情報管理フィールド名 } from "@/types/車室情報管理"; import { 顧客マスタフィールド名 } from "@/types/顧客マスタ"; import { KintoneRestAPIClient } from "@kintone/rest-api-client"; -import { addDays, addMonths, format, setHours, setMonth } from "date-fns"; +import { addDays, format, setHours } from "date-fns"; +import { get, set } from "lodash"; import Swal from "sweetalert2"; const client = new KintoneRestAPIClient(); +const 初回入金予定作成完了 = (入金予定: 入金予定結果) => { + const F = 入金予定結果フィールド名; + if (!入金予定[F.初回振り込み関連申込レコード番号].value) { + throw new Error("初回入金予定でない"); + } + const param = {}; + + if (入金予定[F.支払種別].value === 支払種別Dropdown.定期料金) { + if ( + 入金予定[F.定期料金日割り分].value.find( + (val) => val === 定期料金日割り分Checkbox.該当 + ) + ) { + set( + param, + 定期申込予約フィールド名.初回入金予定_日割り分入金予定, + 入金予定.$id.value + ); + } else { + set( + param, + 定期申込予約フィールド名.初回入金予定_初月分入金予定, + 入金予定.$id.value + ); + } + } else if (入金予定[F.支払種別].value === 支払種別Dropdown.保証金) { + set( + param, + 定期申込予約フィールド名.初回入金予定_保証金入金予定, + 入金予定.$id.value + ); + } else { + throw new Error("想定外の初回入金種別"); + } + bulkRequest.update({ + app: AppID.定期申込予約, + id: 入金予定.first_payment_entry_record_no.value, + record: makeRecordData(param), + }); +}; + const 残金設定 = (record: 入金予定結果) => { record[入金予定結果フィールド名.残金].value = (() => { const amount = @@ -95,10 +134,11 @@ const getCallbackFillAmount = (record: 入金予定結果) => { // クエリパラメータよりフィールドに値をセットする const setData = (event: any, targets: string[]) => { - const param = new URLSearchParams(location.search.replace("?", "")); + const param = parseFromUrlSearchQuery(); targets.forEach((target) => { - const value = param.get(target); - if (value === null) return; + const value = get(param, target); + console.log(target, value); + if (value === undefined) return; 値設定(event, target, value, true); }); }; @@ -119,89 +159,6 @@ const setData = (event: any, targets: string[]) => { }) ); - 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 F = 定期申込予約フィールド名; - const P = 入金予定結果フィールド名; - - const 申込 = await get定期申込予約( - record.first_payment_entry_record_no.value - ); - const 契約 = await get車室情報管理(record.contract_record_number.value); - const プラン = await get定期駐車場プランマスタ( - 契約[車室情報管理フィールド名.プラン名].value - ); - - // 申込の初回振り込み情報を入力する - 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 保証金 = Number(プラン.保証金合計額.value ?? 0); - if (0 < 保証金) { - bulkRequest.create({ - app: AppID.入金予定結果, - record: makeRecordData({ - [P.車室情報管理レコード番号]: record.contract_record_number.value, - [P.支払種別]: 支払種別Dropdown.保証金, - [P.支払方法]: record.payment_method.value ?? "", - [P.支払予定日]: record.payment_plan_date.value ?? "", - [P.支払予定金額]: プラン.保証金合計額.value, - [P.入金額]: "0", - [P.残金]: String(保証金), - }), - }); - } - - const 請求対象分月 = addMonths( - setMonth(new Date(), Number(record.target_month.value) - 1), - Number(record.target_term_month.value) - 1 - ); - - const 日割り対象月 = addMonths(請求対象分月, -1); - - bulkRequest.update({ - app: AppID.定期申込予約, - id: record.first_payment_entry_record_no.value, - record: makeRecordData({ - [F.振込期日]: 支払予定日, - [F.初回振り込み合計額]: 支払予定金額, - [F.請求対象分_月]: String(請求対象分月.getMonth() + 1), - [F.請求対象分_金額]: 申込.定期駐車料金.value, - [F.日割り分_金額]: 日割り金額 === 0 ? "" : String(日割り金額), - [F.日割り分_月]: - 日割り金額 === 0 ? "" : String(日割り対象月.getMonth() + 1), - }), - }); - await bulkRequest.save(); - }; - kintone.events.on( KintoneEvent.追加.レコード追加画面を表示した後, eventHnalder(async (event) => { @@ -216,6 +173,8 @@ const setData = (event: any, targets: string[]) => { 入金予定結果フィールド名.支払対象_利用_月, 入金予定結果フィールド名.支払対象_利用_月間数, 入金予定結果フィールド名.支払予定日, + 入金予定結果フィールド名.定期料金日割り分, + 入金予定結果フィールド名.保証金明細, ]); 残金設定(record); @@ -223,18 +182,6 @@ const setData = (event: any, targets: string[]) => { }) ); - 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) => { @@ -243,13 +190,7 @@ const setData = (event: any, targets: string[]) => { if ( record[入金予定結果フィールド名.初回振り込み関連申込レコード番号].value ) { - // メール送信 - sendEmail(EmailID.申込受付, { - season_ticket_contract_entry_record_no: Number( - record[入金予定結果フィールド名.初回振り込み関連申込レコード番号] - .value - ), - }); + 初回入金予定作成完了(record); // 口座振替登録催促日時を設定する const 口座登録催促日時 = (() => { @@ -265,6 +206,10 @@ const setData = (event: any, targets: string[]) => { [顧客マスタフィールド名.口座登録催促予定日時]: 口座登録催促日時, }), }); + + await bulkRequest.save(); + + if (window.opener) window.opener.location.reload(); } }) ); diff --git a/src/apps/定期申込予約/buttons/保証金入金予定作成ボタン.ts b/src/apps/定期申込予約/buttons/保証金入金予定作成ボタン.ts new file mode 100644 index 0000000..02b0f6c --- /dev/null +++ b/src/apps/定期申込予約/buttons/保証金入金予定作成ボタン.ts @@ -0,0 +1,90 @@ +import { apptemplate } from "@/common/app-template"; +import { AppID } from "@/common/appids"; +import { dateParse, formatDateStr } from "@/common/datetime"; +import { setHeaderButton } from "@/common/header-button"; +import { makeSubTableRecordData } from "@/common/rest-api-client"; +import { getCreateUrl, makeUrlSearchParams } from "@/rest-api/url"; +import { get定期駐車場プランマスタ } from "@/rest-api/定期駐車場プランマスタ"; +import { get車室情報管理 } from "@/rest-api/車室情報管理"; +import { + 保証金明細行データ, + 保証金明細行データ作成, + 入金予定結果フィールド名, + 支払方法Dropdown, + 支払種別Dropdown, +} from "@/types/入金予定結果"; +import { 初回入金予定Checkbox, 定期申込予約 } from "@/types/定期申込予約"; +import { 車室情報管理フィールド名 } from "@/types/車室情報管理"; +import { addDays } from "date-fns"; + +export default function 保証金入金予定作成ボタン(record: 定期申込予約) { + if ( + !!record.自動承認契約情報.value && + record.初回入金予定_必要分.value.includes(初回入金予定Checkbox.保証金) && + !record.初回入金予定_保証金入金予定.value + ) { + setHeaderButton( + "保証金入金予定作成", + apptemplate(async () => { + // 計算 + const 契約 = await get車室情報管理(record.自動承認契約情報.value); + const 契約日 = dateParse(契約.契約日.value); + if (契約日 === null) return; + const プラン = await get定期駐車場プランマスタ( + 契約[車室情報管理フィールド名.プラン名].value + ); + + const 請求金額 = Number(プラン.保証金合計額.value); + const 明細 = (() => { + const ret: 保証金明細行データ[] = []; + + if (0 < Number(プラン.保証金.value)) { + ret.push( + 保証金明細行データ作成({ + [入金予定結果フィールド名.保証金明細_名称]: "保証金", + [入金予定結果フィールド名.保証金明細_金額]: プラン.保証金.value, + }) + ); + } + if (0 < Number(プラン.チェーンゲート保証金.value)) { + ret.push( + 保証金明細行データ作成({ + [入金予定結果フィールド名.保証金明細_名称]: + "チェーンゲート保証金", + [入金予定結果フィールド名.保証金明細_金額]: + プラン.チェーンゲート保証金.value, + }) + ); + } + if (0 < Number(プラン.パスカード保証金.value)) { + ret.push( + 保証金明細行データ作成({ + [入金予定結果フィールド名.保証金明細_名称]: "保証金", + [入金予定結果フィールド名.保証金明細_金額]: + プラン.パスカード保証金.value, + }) + ); + } + return ret; + })(); + const 保証金明細 = makeSubTableRecordData(明細); + + const param = makeUrlSearchParams({ + [入金予定結果フィールド名.車室情報管理レコード番号]: + record.自動承認契約情報.value, + [入金予定結果フィールド名.初回振り込み関連申込レコード番号]: + record.$id.value, + [入金予定結果フィールド名.支払予定金額]: String(請求金額), + [入金予定結果フィールド名.支払方法]: 支払方法Dropdown.振込, + [入金予定結果フィールド名.支払種別]: 支払種別Dropdown.保証金, + [入金予定結果フィールド名.支払予定日]: formatDateStr( + addDays(契約日, -1) + ), + [入金予定結果フィールド名.保証金明細]: 保証金明細, + }); + const url = getCreateUrl(AppID.入金予定結果, param); + window.open(url, "_blank", "popup"); + }) + ); + } +} diff --git a/src/apps/定期申込予約/buttons/初月分入金予定作成ボタン.ts b/src/apps/定期申込予約/buttons/初月分入金予定作成ボタン.ts new file mode 100644 index 0000000..16f5d3e --- /dev/null +++ b/src/apps/定期申込予約/buttons/初月分入金予定作成ボタン.ts @@ -0,0 +1,71 @@ +import { apptemplate } from "@/common/app-template"; +import { AppID } from "@/common/appids"; +import { dateParse, formatDateStr } from "@/common/datetime"; +import { setHeaderButton } from "@/common/header-button"; +import 定期駐車場料金計算 from "@/logic/定期駐車場料金計算"; +import { getCreateUrl, makeUrlSearchParams } from "@/rest-api/url"; +import { get定期駐車場プランマスタ } from "@/rest-api/定期駐車場プランマスタ"; +import { get車室情報管理 } from "@/rest-api/車室情報管理"; +import { + 入金予定結果フィールド名, + 支払方法Dropdown, + 支払種別Dropdown, +} from "@/types/入金予定結果"; +import { 初回入金予定Checkbox, 定期申込予約 } from "@/types/定期申込予約"; +import { 車室情報管理フィールド名 } from "@/types/車室情報管理"; +import { addDays, addMonths, endOfMonth, setDate } from "date-fns"; + +export default function 初月分入金予定作成ボタン(record: 定期申込予約) { + if ( + !!record.自動承認契約情報.value && + record.初回入金予定_必要分.value.includes(初回入金予定Checkbox.初月分) && + !record.初回入金予定_初月分入金予定.value + ) { + setHeaderButton( + "初月分入金予定作成", + apptemplate(async () => { + // 計算 + const 契約 = await get車室情報管理(record.自動承認契約情報.value); + const 契約日 = dateParse(契約.契約日.value); + if (契約日 === null) return; + const プラン = await get定期駐車場プランマスタ( + 契約[車室情報管理フィールド名.プラン名].value + ); + + const 開始日 = (() => { + if (契約日.getDate() === 1) { + return 契約日; + } + return setDate(addMonths(契約日, 1), 1); + })(); + + const 終了日 = endOfMonth(開始日); + + const 計算 = new 定期駐車場料金計算(プラン); + const 請求金額 = 計算.期間の計算(開始日, 終了日); + + const param = makeUrlSearchParams({ + [入金予定結果フィールド名.車室情報管理レコード番号]: + record.自動承認契約情報.value, + [入金予定結果フィールド名.初回振り込み関連申込レコード番号]: + record.$id.value, + [入金予定結果フィールド名.支払予定金額]: String(請求金額), + [入金予定結果フィールド名.支払方法]: 支払方法Dropdown.振込, + [入金予定結果フィールド名.支払種別]: 支払種別Dropdown.定期料金, + [入金予定結果フィールド名.支払対象_利用_年]: String( + 開始日.getFullYear() + ), + [入金予定結果フィールド名.支払対象_利用_月]: String( + 開始日.getMonth() + 1 + ), + [入金予定結果フィールド名.支払対象_利用_月間数]: "1", + [入金予定結果フィールド名.支払予定日]: formatDateStr( + addDays(契約日, -1) + ), + }); + const url = getCreateUrl(AppID.入金予定結果, param); + window.open(url, "_blank", "popup"); + }) + ); + } +} diff --git a/src/apps/定期申込予約/buttons/受付メール送信ボタン.ts b/src/apps/定期申込予約/buttons/受付メール送信ボタン.ts new file mode 100644 index 0000000..de2559d --- /dev/null +++ b/src/apps/定期申込予約/buttons/受付メール送信ボタン.ts @@ -0,0 +1,84 @@ +import { apptemplate } from "@/common/app-template"; +import { AppID } from "@/common/appids"; +import { now } from "@/common/datetime"; +import { setHeaderButton } from "@/common/header-button"; +import { makeDatetimeStr, makeRecordData } from "@/common/rest-api-client"; +import { Message } from "@/exception"; +import { ShowConfirmDialog, SuccessDialog } from "@/middleware/swal"; +import { EmailID, sendEmail } from "@/mypage/メール"; +import bulkRequest from "@/rest-api/bulk"; +import { + 初回入金予定Checkbox, + 定期申込予約, + 定期申込予約フィールド名, +} from "@/types/定期申込予約"; + +const 表示判定 = (record: 定期申込予約): boolean => { + if (!record.自動承認契約情報.value) { + return false; + } + + if ( + record.初回入金予定_必要分.value.includes(初回入金予定Checkbox.初月分) && + !record.初回入金予定_初月分入金予定.value + ) { + return false; + } + if ( + record.初回入金予定_必要分.value.includes(初回入金予定Checkbox.日割り分) && + !record.初回入金予定_日割り分入金予定.value + ) { + return false; + } + if ( + record.初回入金予定_必要分.value.includes(初回入金予定Checkbox.保証金) && + !record.初回入金予定_保証金入金予定.value + ) { + return false; + } + + return true; +}; + +export default function 受付メール送信ボタン(record: 定期申込予約) { + if (表示判定(record)) { + setHeaderButton( + "受付メール送信", + apptemplate(async ({ needReloadAtEnd }) => { + const confirmMessage = (() => { + if (!!record.受付メール送信日時.value) { + return "送信しますか?(再送信)"; + } + return "送信しますか?"; + })(); + const confirm = await ShowConfirmDialog({ + text: confirmMessage, + }); + if (!confirm.isConfirmed) return; + + // メール送信 + const emailSuccess = await sendEmail(EmailID.申込受付, { + season_ticket_contract_entry_record_no: Number(record.$id.value), + }); + + if (!emailSuccess) { + throw new Message("メール送信に失敗しました"); + } + + bulkRequest.update({ + app: AppID.定期申込予約, + id: record.$id.value, + record: makeRecordData({ + [定期申込予約フィールド名.受付メール送信日時]: makeDatetimeStr( + now() + ), + }), + }); + + await bulkRequest.save(); + await SuccessDialog.fire(); + needReloadAtEnd(true); + }) + ); + } +} diff --git a/src/apps/定期申込予約/buttons/日割り入金予定作成ボタン.ts b/src/apps/定期申込予約/buttons/日割り入金予定作成ボタン.ts new file mode 100644 index 0000000..09314db --- /dev/null +++ b/src/apps/定期申込予約/buttons/日割り入金予定作成ボタン.ts @@ -0,0 +1,67 @@ +import { apptemplate } from "@/common/app-template"; +import { AppID } from "@/common/appids"; +import { dateParse, formatDateStr } from "@/common/datetime"; +import { setHeaderButton } from "@/common/header-button"; +import 定期駐車場料金計算 from "@/logic/定期駐車場料金計算"; +import { getCreateUrl, makeUrlSearchParams } from "@/rest-api/url"; +import { get定期駐車場プランマスタ } from "@/rest-api/定期駐車場プランマスタ"; +import { get車室情報管理 } from "@/rest-api/車室情報管理"; +import { + 入金予定結果フィールド名, + 定期料金日割り分Checkbox, + 支払方法Dropdown, + 支払種別Dropdown, +} from "@/types/入金予定結果"; +import { 初回入金予定Checkbox, 定期申込予約 } from "@/types/定期申込予約"; +import { 車室情報管理フィールド名 } from "@/types/車室情報管理"; +import { addDays, endOfMonth } from "date-fns"; + +export default function 日割り入金予定作成ボタン(record: 定期申込予約) { + if ( + !!record.自動承認契約情報.value && + record.初回入金予定_必要分.value.includes(初回入金予定Checkbox.日割り分) && + !record.初回入金予定_日割り分入金予定.value + ) { + setHeaderButton( + "日割り分入金予定作成", + apptemplate(async () => { + // 計算 + const 契約 = await get車室情報管理(record.自動承認契約情報.value); + const 契約日 = dateParse(契約.契約日.value); + if (契約日 === null) return; + const プラン = await get定期駐車場プランマスタ( + 契約[車室情報管理フィールド名.プラン名].value + ); + + const 月末 = endOfMonth(契約日); + const 計算 = new 定期駐車場料金計算(プラン); + const 請求金額 = 計算.期間の計算(契約日, 月末); + + const param = makeUrlSearchParams({ + [入金予定結果フィールド名.車室情報管理レコード番号]: + record.自動承認契約情報.value, + [入金予定結果フィールド名.初回振り込み関連申込レコード番号]: + record.$id.value, + [入金予定結果フィールド名.支払予定金額]: String(請求金額), + [入金予定結果フィールド名.支払方法]: 支払方法Dropdown.振込, + [入金予定結果フィールド名.支払種別]: 支払種別Dropdown.定期料金, + [入金予定結果フィールド名.支払対象_利用_年]: String( + 契約日.getFullYear() + ), + [入金予定結果フィールド名.支払対象_利用_月]: String( + 契約日.getMonth() + 1 + ), + [入金予定結果フィールド名.支払対象_利用_月間数]: "1", + [入金予定結果フィールド名.支払予定日]: formatDateStr( + addDays(契約日, -1) + ), + [入金予定結果フィールド名.定期料金日割り分]: [ + 定期料金日割り分Checkbox.該当, + ], + }); + const url = getCreateUrl(AppID.入金予定結果, param); + window.open(url, "_blank", "popup"); + }) + ); + } +} diff --git a/src/apps/定期申込予約/buttons/自動承認ボタン.ts b/src/apps/定期申込予約/buttons/自動承認ボタン.ts new file mode 100644 index 0000000..865001c --- /dev/null +++ b/src/apps/定期申込予約/buttons/自動承認ボタン.ts @@ -0,0 +1,59 @@ +import { apptemplate } from "@/common/app-template"; +import { setHeaderButton } from "@/common/header-button"; +import { 契約情報更新イベント } from "@/event/契約情報更新"; +import { Message } from "@/exception"; +import { + ShowConfirmDialog, + SuccessDialog, + WarningDialog, +} from "@/middleware/swal"; +import { 定期申込予約, 状態Dropdown } from "@/types/定期申込予約"; +import { 申込 } from "../自動承認"; + +const 表示判定 = (record: 定期申込予約): boolean => { + const S = 状態Dropdown; + if ( + ![S.新規, S.選考当選, S.予約, S.空き待ち].find((status) => { + return status === record.status.value; + }) + ) { + return false; + } + + return true; +}; + +export default function 自動承認ボタン(record: 定期申込予約) { + if (表示判定(record)) { + setHeaderButton( + "受付", + apptemplate(async ({ setEvent, needReloadAtEnd }) => { + if (record.台数.value !== "1") { + throw new Message("台数を1にしてください"); + } + + const confirm = await ShowConfirmDialog({ + text: "承認しますか", + }); + if (!confirm.isConfirmed) return; + + const entry = new 申込(record); + await entry.初期化(); + await entry.選定(); + + await SuccessDialog.fire(); + + await WarningDialog.fire({ + timer: 2000, + timerProgressBar: true, + text: "各初回請求データを作成してください", + }); + const 契約 = entry.作成後契約取得(); + if (!契約) throw new Error(); + + setEvent(new 契約情報更新イベント().getEvent(契約)); + needReloadAtEnd(true); + }) + ); + } +} diff --git a/src/apps/定期申込予約/index.tsx b/src/apps/定期申込予約/index.tsx index 2342c74..8eb6c8d 100644 --- a/src/apps/定期申込予約/index.tsx +++ b/src/apps/定期申込予約/index.tsx @@ -1,75 +1,13 @@ -import { apptemplate, eventHnalder } from "@/common/app-template"; -import { AppID } from "@/common/appids"; -import { initMenuBox, setHeaderButton } from "@/common/header-button"; +import { eventHnalder } from "@/common/app-template"; +import { initMenuBox } from "@/common/header-button"; import { KintoneEvent } from "@/common/kintone-event"; -import { 契約情報更新イベント } from "@/event/契約情報更新"; -import { - ShowConfirmDialog, - SuccessDialog, - WarningDialog, -} from "@/middleware/swal"; -import { getCreateUrl, getDetailUrl } from "@/rest-api/url"; -import { - 入金予定結果フィールド名, - 支払方法Dropdown, - 支払種別Dropdown, -} from "@/types/入金予定結果"; -import { 定期申込予約, 状態Dropdown } from "@/types/定期申込予約"; +import { 定期申込予約 } from "@/types/定期申込予約"; import { setup } from ".."; -import { 申込 } from "./自動承認"; -import { get車室情報管理 } from "@/rest-api/車室情報管理"; -import { dateParse, formatDateStr, now } from "@/common/datetime"; -import { - addDays, - addMonths, - differenceInMonths, - endOfMonth, - getDaysInMonth, -} from "date-fns"; -import 定期駐車場料金計算 from "@/logic/定期駐車場料金計算"; -import { get定期駐車場プランマスタ } from "@/rest-api/定期駐車場プランマスタ"; -import { 車室情報2フィールド名 } from "@/types/車室情報2"; -import { 車室情報管理フィールド名 } from "@/types/車室情報管理"; -import { get定期申込予約 } from "@/rest-api/定期申込予約"; - -const 初回入金予定作成画面オープン = async (record: 定期申込予約) => { - // 計算 - const 契約 = await get車室情報管理(record.自動承認契約情報.value); - const 契約日 = dateParse(契約.契約日.value); - if (契約日 === null) return; - const プラン = await get定期駐車場プランマスタ( - 契約[車室情報管理フィールド名.プラン名].value - ); - const 請求終了日: Date = (() => { - // 実行日基準に翌月の末日 - const 基準日1 = endOfMonth(addMonths(now(), 1)); - // 開始月の月末 - const 基準日2 = endOfMonth(契約日); - - return 基準日1 < 基準日2 ? 基準日2 : 基準日1; - })(); - - const 計算 = new 定期駐車場料金計算(プラン); - const 請求金額 = 計算.期間の計算(契約日, 請求終了日); - - const param = new URLSearchParams({ - [入金予定結果フィールド名.車室情報管理レコード番号]: - record.自動承認契約情報.value, - [入金予定結果フィールド名.初回振り込み関連申込レコード番号]: - record.$id.value, - [入金予定結果フィールド名.支払予定金額]: String(請求金額), - [入金予定結果フィールド名.支払方法]: 支払方法Dropdown.振込, - [入金予定結果フィールド名.支払種別]: 支払種別Dropdown.定期料金, - [入金予定結果フィールド名.支払対象_利用_年]: String(契約日.getFullYear()), - [入金予定結果フィールド名.支払対象_利用_月]: String(契約日.getMonth() + 1), - [入金予定結果フィールド名.支払対象_利用_月間数]: String( - differenceInMonths(請求終了日, 契約日) + 1 - ), - [入金予定結果フィールド名.支払予定日]: formatDateStr(addDays(契約日, -1)), - }); - const url = getCreateUrl(AppID.入金予定結果, param); - window.open(url); -}; +import 保証金入金予定作成ボタン from "./buttons/保証金入金予定作成ボタン"; +import 初月分入金予定作成ボタン from "./buttons/初月分入金予定作成ボタン"; +import 受付メール送信ボタン from "./buttons/受付メール送信ボタン"; +import 日割り入金予定作成ボタン from "./buttons/日割り入金予定作成ボタン"; +import 自動承認ボタン from "./buttons/自動承認ボタン"; setup(() => { kintone.events.on( @@ -79,60 +17,11 @@ setup(() => { await initMenuBox(); - const S = 状態Dropdown; - if ( - [S.新規, S.選考当選, S.予約, S.空き待ち].find((status) => { - return status === record.status.value; - }) && - record.台数.value === "1" - ) { - setHeaderButton( - "自動承認", - apptemplate(async ({ setEvent, needReloadAtEnd }) => { - const confirm = await ShowConfirmDialog({ - text: "承認しますか", - }); - if (!confirm.isConfirmed) return; - - const entry = new 申込(record); - await entry.初期化(); - await entry.選定(); - - await SuccessDialog.fire(); - - await WarningDialog.fire({ - timer: 2000, - timerProgressBar: true, - text: "初回請求データを作成してください", - }); - const 契約 = entry.作成後契約取得(); - if (!契約) throw new Error(); - - // 入金予定アプリ画面オープン - { - const 申込 = await get定期申込予約(record.$id.value); - await 初回入金予定作成画面オープン(申込); - } - - setEvent(new 契約情報更新イベント().getEvent(契約)); - needReloadAtEnd(true); - }) - ); - } - - if ( - !!record.自動承認契約情報.value && - [S.承認_手動, S.承認_自動承認].find((status) => { - return status === record.status.value; - }) - ) { - setHeaderButton( - "初回入金予定作成", - apptemplate(async () => { - 初回入金予定作成画面オープン(record); - }) - ); - } + 自動承認ボタン(record); + 初月分入金予定作成ボタン(record); + 日割り入金予定作成ボタン(record); + 保証金入金予定作成ボタン(record); + 受付メール送信ボタン(record); }) ); }); diff --git a/src/apps/定期申込予約/自動承認.ts b/src/apps/定期申込予約/自動承認.ts index bf20fe0..d12be25 100644 --- a/src/apps/定期申込予約/自動承認.ts +++ b/src/apps/定期申込予約/自動承認.ts @@ -12,6 +12,7 @@ import { get顧客マスタ, } from "@/rest-api/顧客マスタ"; import { + 初回入金予定Checkbox, 定期申込予約, 定期申込予約フィールド名, 状態Dropdown, @@ -253,6 +254,21 @@ export class 申込 { [F.状態]: 状態Dropdown.承認_自動承認, [F.自動承認ステータス]: 自動承認ステータスDropdown.承認済, [F.定期駐車料金]: this.プラン.契約金額.value, + [F.初回入金予定_必要分]: (() => { + const ret: string[] = []; + + ret.push(初回入金予定Checkbox.初月分); + const 契約日 = dateParse(this.定期申込予約.利用開始希望日.value); + if (!契約日) throw new Error("契約日不正"); + if (契約日.getDate() !== 1) { + ret.push(初回入金予定Checkbox.日割り分); + } + if (0 < Number(this.プラン.保証金合計額.value)) { + ret.push(初回入金予定Checkbox.保証金); + } + + return ret; + })(), }), }, async () => { diff --git a/src/common/datetime.ts b/src/common/datetime.ts index 1733bde..7e71062 100644 --- a/src/common/datetime.ts +++ b/src/common/datetime.ts @@ -9,8 +9,8 @@ import { } from "date-fns"; export const DEFAULT_DATE_FORMAT = "yyyy-MM-dd"; -export const DEFAULT_DATE_TIME_FORMAT = "yyyy/MM/dd HH:mm:ss"; -export const DEFAULT_DATE_TIME_FORMAT_ANOTHER1 = "yyyy-MM-dd HH:mm:ss"; +export const DEFAULT_DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss"; +export const DEFAULT_DATE_TIME_FORMAT_ANOTHER1 = "yyyy/MM/dd HH:mm:ss"; export const DEFAULT_YYYYMM_FORMAT = "yyyyMM"; type Input = Date | string | null | undefined; @@ -26,7 +26,7 @@ export const formatYYYYMMStr = (source: Date | string | null | undefined) => { return formatToStr(source, DEFAULT_YYYYMM_FORMAT); }; -const formatToStr = (source: Input, formatStr: string) => { +export const formatToStr = (source: Input, formatStr: string) => { if (source === null || source === undefined) return ""; if (source instanceof Date) return format(source, formatStr); return format(parseISO(source), formatStr); diff --git a/src/common/rest-api-client.ts b/src/common/rest-api-client.ts index 21951f7..893ca44 100644 --- a/src/common/rest-api-client.ts +++ b/src/common/rest-api-client.ts @@ -1,3 +1,6 @@ +import { get } from "lodash"; +import { formatDateStr } from "./datetime"; + export type Field = { [fieldCode: string]: { value: unknown; @@ -27,3 +30,26 @@ export const makeRecordData = (data: { }); return ret; }; + +export const makeSubTableRecordData = (data: { [key: string]: any }[]) => { + const ret = data.map((row) => { + const obj: { + value: { + [key: string]: object; + }; + } = { value: {} }; + Object.keys(row).forEach((key) => { + const val = get(row, key); + obj.value[key] = val; + }); + return obj; + }); + return ret; +}; + +export const makeDatetimeStr = (data: Date): string => { + return data.toISOString(); +}; +export const makeDateDatetime = (data: Date): string => { + return formatDateStr(data); +}; diff --git a/src/rest-api/url.ts b/src/rest-api/url.ts index 40b9bb2..e8b89a4 100644 --- a/src/rest-api/url.ts +++ b/src/rest-api/url.ts @@ -1,4 +1,5 @@ import { AppID } from "@/common/appids"; +import { get } from "lodash"; import { sprintf } from "sprintf"; export const getDetailUrl = (app: AppID, レコード番号: string | number) => { @@ -15,3 +16,24 @@ export const getCreateUrl = (app: AppID, param?: URLSearchParams) => { !!param ? param.toString() : "" ); }; + +export const makeUrlSearchParams = (data: object) => { + const param = new URLSearchParams(); + Object.keys(data).forEach((key) => { + const val = get(data, key); + param.append(key, JSON.stringify(val)); + console.log("append", key, val, JSON.stringify(val), data); + }); + return param; +}; + +export const parseFromUrlSearchQuery = () => { + const param = new URLSearchParams(location.search.replace("?", "")); + + const obj: { [key: string]: string } = {}; + for (const [key, value] of param.entries()) { + obj[key] = JSON.parse(value); + } + + return obj; +}; diff --git a/src/types/入金予定結果.ts b/src/types/入金予定結果.ts index 5a5d75e..972d2ec 100644 --- a/src/types/入金予定結果.ts +++ b/src/types/入金予定結果.ts @@ -1,5 +1,6 @@ import { KintoneRecordField } from "@kintone/rest-api-client"; import { AppRecord } from "."; +import { get, has, set } from "lodash"; const F = { 車室情報管理レコード番号: "contract_record_number", @@ -15,6 +16,11 @@ const F = { 初回振り込み関連申込レコード番号: "first_payment_entry_record_no", 支払方法: "payment_method", 支払種別: "payment_type", + 定期料金日割り分: "定期料金日割り分", + + 保証金明細: "保証金明細", + 保証金明細_名称: "保証金明細_名称", + 保証金明細_金額: "保証金明細_金額", } as const; export const 支払種別Dropdown = { @@ -38,6 +44,31 @@ export const 支払方法Dropdown = { export type 支払方法Dropdown = (typeof 支払方法Dropdown)[keyof typeof 支払方法Dropdown]; +export const 定期料金日割り分Checkbox = { + 該当: "該当", +} as const; +export type 定期料金日割り分Checkbox = + (typeof 定期料金日割り分Checkbox)[keyof typeof 定期料金日割り分Checkbox]; + +export type 保証金明細行データ = { + 保証金明細_名称: KintoneRecordField.SingleLineText; + 保証金明細_金額: KintoneRecordField.Number; +}; +export const 保証金明細行データ作成 = (data: object): 保証金明細行データ => { + const row: 保証金明細行データ = { + 保証金明細_名称: { value: "", type: "SINGLE_LINE_TEXT" }, + 保証金明細_金額: { value: "", type: "NUMBER" }, + }; + + Object.keys(row).forEach((target) => { + if (has(data, target)) { + set(row, target + ".value", get(data, target)); + } + }); + + return row; +}; + export const 入金予定結果フィールド名 = F; export type 入金予定結果 = AppRecord & { @@ -58,4 +89,12 @@ export type 入金予定結果 = AppRecord & { customer_code: KintoneRecordField.Number; [F.支払方法]: KintoneRecordField.Dropdown; [F.初回振り込み関連申込レコード番号]: KintoneRecordField.Number; + 定期料金日割り分: KintoneRecordField.CheckBox; + 保証金明細: { + type: "SUBTABLE"; + value: { + id: string; + value: 保証金明細行データ; + }[]; + }; }; diff --git a/src/types/定期申込予約.ts b/src/types/定期申込予約.ts index 5a7f28e..52729a7 100644 --- a/src/types/定期申込予約.ts +++ b/src/types/定期申込予約.ts @@ -14,6 +14,12 @@ const F = { 請求対象分_金額: "請求対象分_金額", 初回振り込み合計額: "初回振り込み合計額", 自動承認契約情報: "自動承認契約情報", + 受付メール送信日時: "受付メール送信日時", + 承認メール送信日時: "承認メール送信日時", + 初回入金予定_必要分: "初回入金予定_必要分", + 初回入金予定_初月分入金予定: "初回入金予定_初月分入金予定", + 初回入金予定_日割り分入金予定: "初回入金予定_日割り分入金予定", + 初回入金予定_保証金入金予定: "初回入金予定_保証金入金予定", } as const; export const 状態Dropdown = { @@ -36,6 +42,14 @@ export const 自動承認ステータスDropdown = { export type 自動承認ステータスDropdown = (typeof 自動承認ステータスDropdown)[keyof typeof 自動承認ステータスDropdown]; +export const 初回入金予定Checkbox = { + 初月分: "初月分", + 日割り分: "日割り分", + 保証金: "保証金", +} as const; +export type 初回入金予定Checkbox = + (typeof 初回入金予定Checkbox)[keyof typeof 初回入金予定Checkbox]; + export const 定期申込予約フィールド名 = F; export type 定期申込予約 = AppRecord & { @@ -75,4 +89,11 @@ export type 定期申込予約 = AppRecord & { [F.自動承認ステータス]: KintoneRecordField.SingleLineText; [F.状態]: KintoneRecordField.Dropdown; [F.自動承認契約情報]: KintoneRecordField.Number; + [F.自動承認契約情報]: KintoneRecordField.Number; + [F.受付メール送信日時]: KintoneRecordField.DateTime; + [F.承認メール送信日時]: KintoneRecordField.DateTime; + [F.初回入金予定_必要分]: KintoneRecordField.CheckBox; + [F.初回入金予定_初月分入金予定]: KintoneRecordField.SingleLineText; + [F.初回入金予定_日割り分入金予定]: KintoneRecordField.SingleLineText; + [F.初回入金予定_保証金入金予定]: KintoneRecordField.SingleLineText; };